[Mlir-commits] [mlir] 3aa20c2 - [mlir][spirv] Add definition for selected sample operations (#129558)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Mon Mar 24 06:56:41 PDT 2025


Author: Igor Wodiany
Date: 2025-03-24T13:56:36Z
New Revision: 3aa20c266c97a638c63b5368d89fe25757885178

URL: https://github.com/llvm/llvm-project/commit/3aa20c266c97a638c63b5368d89fe25757885178
DIFF: https://github.com/llvm/llvm-project/commit/3aa20c266c97a638c63b5368d89fe25757885178.diff

LOG: [mlir][spirv] Add definition for selected sample operations (#129558)

This commit adds following three operations: ImageSampleImplicitLodOp,
ImageSampleExplicitLodOp and ImageSampleProjDrefImplicitLodOp

Added: 
    mlir/include/mlir/Dialect/SPIRV/Interfaces/CMakeLists.txt
    mlir/include/mlir/Dialect/SPIRV/Interfaces/SPIRVImageInterfaces.h
    mlir/include/mlir/Dialect/SPIRV/Interfaces/SPIRVImageInterfaces.td
    mlir/lib/Dialect/SPIRV/Interfaces/CMakeLists.txt
    mlir/lib/Dialect/SPIRV/Interfaces/SPIRVImageInterfaces.cpp

Modified: 
    mlir/include/mlir/Dialect/SPIRV/CMakeLists.txt
    mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td
    mlir/include/mlir/Dialect/SPIRV/IR/SPIRVImageOps.td
    mlir/include/mlir/Dialect/SPIRV/IR/SPIRVOps.h
    mlir/lib/Dialect/SPIRV/CMakeLists.txt
    mlir/lib/Dialect/SPIRV/IR/CMakeLists.txt
    mlir/lib/Dialect/SPIRV/IR/ImageOps.cpp
    mlir/test/Dialect/SPIRV/IR/image-ops.mlir
    mlir/test/Target/SPIRV/image-ops.mlir

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/Dialect/SPIRV/CMakeLists.txt b/mlir/include/mlir/Dialect/SPIRV/CMakeLists.txt
index 9f57627c321fb..0e2b2af11346f 100644
--- a/mlir/include/mlir/Dialect/SPIRV/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/SPIRV/CMakeLists.txt
@@ -1,2 +1,3 @@
 add_subdirectory(IR)
+add_subdirectory(Interfaces)
 add_subdirectory(Transforms)

diff  --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td
index cafe140469570..d5359da2a590e 100644
--- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td
+++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td
@@ -4274,242 +4274,245 @@ class SPIRV_OpCode<string name, int val> {
 
 // Begin opcode section. Generated from SPIR-V spec; DO NOT MODIFY!
 
-def SPIRV_OC_OpNop                           : I32EnumAttrCase<"OpNop", 0>;
-def SPIRV_OC_OpUndef                         : I32EnumAttrCase<"OpUndef", 1>;
-def SPIRV_OC_OpSourceContinued               : I32EnumAttrCase<"OpSourceContinued", 2>;
-def SPIRV_OC_OpSource                        : I32EnumAttrCase<"OpSource", 3>;
-def SPIRV_OC_OpSourceExtension               : I32EnumAttrCase<"OpSourceExtension", 4>;
-def SPIRV_OC_OpName                          : I32EnumAttrCase<"OpName", 5>;
-def SPIRV_OC_OpMemberName                    : I32EnumAttrCase<"OpMemberName", 6>;
-def SPIRV_OC_OpString                        : I32EnumAttrCase<"OpString", 7>;
-def SPIRV_OC_OpLine                          : I32EnumAttrCase<"OpLine", 8>;
-def SPIRV_OC_OpExtension                     : I32EnumAttrCase<"OpExtension", 10>;
-def SPIRV_OC_OpExtInstImport                 : I32EnumAttrCase<"OpExtInstImport", 11>;
-def SPIRV_OC_OpExtInst                       : I32EnumAttrCase<"OpExtInst", 12>;
-def SPIRV_OC_OpMemoryModel                   : I32EnumAttrCase<"OpMemoryModel", 14>;
-def SPIRV_OC_OpEntryPoint                    : I32EnumAttrCase<"OpEntryPoint", 15>;
-def SPIRV_OC_OpExecutionMode                 : I32EnumAttrCase<"OpExecutionMode", 16>;
-def SPIRV_OC_OpCapability                    : I32EnumAttrCase<"OpCapability", 17>;
-def SPIRV_OC_OpTypeVoid                      : I32EnumAttrCase<"OpTypeVoid", 19>;
-def SPIRV_OC_OpTypeBool                      : I32EnumAttrCase<"OpTypeBool", 20>;
-def SPIRV_OC_OpTypeInt                       : I32EnumAttrCase<"OpTypeInt", 21>;
-def SPIRV_OC_OpTypeFloat                     : I32EnumAttrCase<"OpTypeFloat", 22>;
-def SPIRV_OC_OpTypeVector                    : I32EnumAttrCase<"OpTypeVector", 23>;
-def SPIRV_OC_OpTypeMatrix                    : I32EnumAttrCase<"OpTypeMatrix", 24>;
-def SPIRV_OC_OpTypeImage                     : I32EnumAttrCase<"OpTypeImage", 25>;
-def SPIRV_OC_OpTypeSampledImage              : I32EnumAttrCase<"OpTypeSampledImage", 27>;
-def SPIRV_OC_OpTypeArray                     : I32EnumAttrCase<"OpTypeArray", 28>;
-def SPIRV_OC_OpTypeRuntimeArray              : I32EnumAttrCase<"OpTypeRuntimeArray", 29>;
-def SPIRV_OC_OpTypeStruct                    : I32EnumAttrCase<"OpTypeStruct", 30>;
-def SPIRV_OC_OpTypePointer                   : I32EnumAttrCase<"OpTypePointer", 32>;
-def SPIRV_OC_OpTypeFunction                  : I32EnumAttrCase<"OpTypeFunction", 33>;
-def SPIRV_OC_OpTypeForwardPointer            : I32EnumAttrCase<"OpTypeForwardPointer", 39>;
-def SPIRV_OC_OpConstantTrue                  : I32EnumAttrCase<"OpConstantTrue", 41>;
-def SPIRV_OC_OpConstantFalse                 : I32EnumAttrCase<"OpConstantFalse", 42>;
-def SPIRV_OC_OpConstant                      : I32EnumAttrCase<"OpConstant", 43>;
-def SPIRV_OC_OpConstantComposite             : I32EnumAttrCase<"OpConstantComposite", 44>;
-def SPIRV_OC_OpConstantNull                  : I32EnumAttrCase<"OpConstantNull", 46>;
-def SPIRV_OC_OpSpecConstantTrue              : I32EnumAttrCase<"OpSpecConstantTrue", 48>;
-def SPIRV_OC_OpSpecConstantFalse             : I32EnumAttrCase<"OpSpecConstantFalse", 49>;
-def SPIRV_OC_OpSpecConstant                  : I32EnumAttrCase<"OpSpecConstant", 50>;
-def SPIRV_OC_OpSpecConstantComposite         : I32EnumAttrCase<"OpSpecConstantComposite", 51>;
-def SPIRV_OC_OpSpecConstantOp                : I32EnumAttrCase<"OpSpecConstantOp", 52>;
-def SPIRV_OC_OpFunction                      : I32EnumAttrCase<"OpFunction", 54>;
-def SPIRV_OC_OpFunctionParameter             : I32EnumAttrCase<"OpFunctionParameter", 55>;
-def SPIRV_OC_OpFunctionEnd                   : I32EnumAttrCase<"OpFunctionEnd", 56>;
-def SPIRV_OC_OpFunctionCall                  : I32EnumAttrCase<"OpFunctionCall", 57>;
-def SPIRV_OC_OpVariable                      : I32EnumAttrCase<"OpVariable", 59>;
-def SPIRV_OC_OpLoad                          : I32EnumAttrCase<"OpLoad", 61>;
-def SPIRV_OC_OpStore                         : I32EnumAttrCase<"OpStore", 62>;
-def SPIRV_OC_OpCopyMemory                    : I32EnumAttrCase<"OpCopyMemory", 63>;
-def SPIRV_OC_OpAccessChain                   : I32EnumAttrCase<"OpAccessChain", 65>;
-def SPIRV_OC_OpPtrAccessChain                : I32EnumAttrCase<"OpPtrAccessChain", 67>;
-def SPIRV_OC_OpInBoundsPtrAccessChain        : I32EnumAttrCase<"OpInBoundsPtrAccessChain", 70>;
-def SPIRV_OC_OpDecorate                      : I32EnumAttrCase<"OpDecorate", 71>;
-def SPIRV_OC_OpMemberDecorate                : I32EnumAttrCase<"OpMemberDecorate", 72>;
-def SPIRV_OC_OpVectorExtractDynamic          : I32EnumAttrCase<"OpVectorExtractDynamic", 77>;
-def SPIRV_OC_OpVectorInsertDynamic           : I32EnumAttrCase<"OpVectorInsertDynamic", 78>;
-def SPIRV_OC_OpVectorShuffle                 : I32EnumAttrCase<"OpVectorShuffle", 79>;
-def SPIRV_OC_OpCompositeConstruct            : I32EnumAttrCase<"OpCompositeConstruct", 80>;
-def SPIRV_OC_OpCompositeExtract              : I32EnumAttrCase<"OpCompositeExtract", 81>;
-def SPIRV_OC_OpCompositeInsert               : I32EnumAttrCase<"OpCompositeInsert", 82>;
-def SPIRV_OC_OpTranspose                     : I32EnumAttrCase<"OpTranspose", 84>;
-def SPIRV_OC_OpImageDrefGather               : I32EnumAttrCase<"OpImageDrefGather", 97>;
-def SPIRV_OC_OpImageWrite                    : I32EnumAttrCase<"OpImageWrite", 99>;
-def SPIRV_OC_OpImage                         : I32EnumAttrCase<"OpImage", 100>;
-def SPIRV_OC_OpImageQuerySize                : I32EnumAttrCase<"OpImageQuerySize", 104>;
-def SPIRV_OC_OpConvertFToU                   : I32EnumAttrCase<"OpConvertFToU", 109>;
-def SPIRV_OC_OpConvertFToS                   : I32EnumAttrCase<"OpConvertFToS", 110>;
-def SPIRV_OC_OpConvertSToF                   : I32EnumAttrCase<"OpConvertSToF", 111>;
-def SPIRV_OC_OpConvertUToF                   : I32EnumAttrCase<"OpConvertUToF", 112>;
-def SPIRV_OC_OpUConvert                      : I32EnumAttrCase<"OpUConvert", 113>;
-def SPIRV_OC_OpSConvert                      : I32EnumAttrCase<"OpSConvert", 114>;
-def SPIRV_OC_OpFConvert                      : I32EnumAttrCase<"OpFConvert", 115>;
-def SPIRV_OC_OpConvertPtrToU                 : I32EnumAttrCase<"OpConvertPtrToU", 117>;
-def SPIRV_OC_OpConvertUToPtr                 : I32EnumAttrCase<"OpConvertUToPtr", 120>;
-def SPIRV_OC_OpPtrCastToGeneric              : I32EnumAttrCase<"OpPtrCastToGeneric", 121>;
-def SPIRV_OC_OpGenericCastToPtr              : I32EnumAttrCase<"OpGenericCastToPtr", 122>;
-def SPIRV_OC_OpGenericCastToPtrExplicit      : I32EnumAttrCase<"OpGenericCastToPtrExplicit", 123>;
-def SPIRV_OC_OpBitcast                       : I32EnumAttrCase<"OpBitcast", 124>;
-def SPIRV_OC_OpSNegate                       : I32EnumAttrCase<"OpSNegate", 126>;
-def SPIRV_OC_OpFNegate                       : I32EnumAttrCase<"OpFNegate", 127>;
-def SPIRV_OC_OpIAdd                          : I32EnumAttrCase<"OpIAdd", 128>;
-def SPIRV_OC_OpFAdd                          : I32EnumAttrCase<"OpFAdd", 129>;
-def SPIRV_OC_OpISub                          : I32EnumAttrCase<"OpISub", 130>;
-def SPIRV_OC_OpFSub                          : I32EnumAttrCase<"OpFSub", 131>;
-def SPIRV_OC_OpIMul                          : I32EnumAttrCase<"OpIMul", 132>;
-def SPIRV_OC_OpFMul                          : I32EnumAttrCase<"OpFMul", 133>;
-def SPIRV_OC_OpUDiv                          : I32EnumAttrCase<"OpUDiv", 134>;
-def SPIRV_OC_OpSDiv                          : I32EnumAttrCase<"OpSDiv", 135>;
-def SPIRV_OC_OpFDiv                          : I32EnumAttrCase<"OpFDiv", 136>;
-def SPIRV_OC_OpUMod                          : I32EnumAttrCase<"OpUMod", 137>;
-def SPIRV_OC_OpSRem                          : I32EnumAttrCase<"OpSRem", 138>;
-def SPIRV_OC_OpSMod                          : I32EnumAttrCase<"OpSMod", 139>;
-def SPIRV_OC_OpFRem                          : I32EnumAttrCase<"OpFRem", 140>;
-def SPIRV_OC_OpFMod                          : I32EnumAttrCase<"OpFMod", 141>;
-def SPIRV_OC_OpVectorTimesScalar             : I32EnumAttrCase<"OpVectorTimesScalar", 142>;
-def SPIRV_OC_OpMatrixTimesScalar             : I32EnumAttrCase<"OpMatrixTimesScalar", 143>;
-def SPIRV_OC_OpVectorTimesMatrix             : I32EnumAttrCase<"OpVectorTimesMatrix", 144>;
-def SPIRV_OC_OpMatrixTimesVector             : I32EnumAttrCase<"OpMatrixTimesVector", 145>;
-def SPIRV_OC_OpMatrixTimesMatrix             : I32EnumAttrCase<"OpMatrixTimesMatrix", 146>;
-def SPIRV_OC_OpDot                           : I32EnumAttrCase<"OpDot", 148>;
-def SPIRV_OC_OpIAddCarry                     : I32EnumAttrCase<"OpIAddCarry", 149>;
-def SPIRV_OC_OpISubBorrow                    : I32EnumAttrCase<"OpISubBorrow", 150>;
-def SPIRV_OC_OpUMulExtended                  : I32EnumAttrCase<"OpUMulExtended", 151>;
-def SPIRV_OC_OpSMulExtended                  : I32EnumAttrCase<"OpSMulExtended", 152>;
-def SPIRV_OC_OpIsNan                         : I32EnumAttrCase<"OpIsNan", 156>;
-def SPIRV_OC_OpIsInf                         : I32EnumAttrCase<"OpIsInf", 157>;
-def SPIRV_OC_OpOrdered                       : I32EnumAttrCase<"OpOrdered", 162>;
-def SPIRV_OC_OpUnordered                     : I32EnumAttrCase<"OpUnordered", 163>;
-def SPIRV_OC_OpLogicalEqual                  : I32EnumAttrCase<"OpLogicalEqual", 164>;
-def SPIRV_OC_OpLogicalNotEqual               : I32EnumAttrCase<"OpLogicalNotEqual", 165>;
-def SPIRV_OC_OpLogicalOr                     : I32EnumAttrCase<"OpLogicalOr", 166>;
-def SPIRV_OC_OpLogicalAnd                    : I32EnumAttrCase<"OpLogicalAnd", 167>;
-def SPIRV_OC_OpLogicalNot                    : I32EnumAttrCase<"OpLogicalNot", 168>;
-def SPIRV_OC_OpSelect                        : I32EnumAttrCase<"OpSelect", 169>;
-def SPIRV_OC_OpIEqual                        : I32EnumAttrCase<"OpIEqual", 170>;
-def SPIRV_OC_OpINotEqual                     : I32EnumAttrCase<"OpINotEqual", 171>;
-def SPIRV_OC_OpUGreaterThan                  : I32EnumAttrCase<"OpUGreaterThan", 172>;
-def SPIRV_OC_OpSGreaterThan                  : I32EnumAttrCase<"OpSGreaterThan", 173>;
-def SPIRV_OC_OpUGreaterThanEqual             : I32EnumAttrCase<"OpUGreaterThanEqual", 174>;
-def SPIRV_OC_OpSGreaterThanEqual             : I32EnumAttrCase<"OpSGreaterThanEqual", 175>;
-def SPIRV_OC_OpULessThan                     : I32EnumAttrCase<"OpULessThan", 176>;
-def SPIRV_OC_OpSLessThan                     : I32EnumAttrCase<"OpSLessThan", 177>;
-def SPIRV_OC_OpULessThanEqual                : I32EnumAttrCase<"OpULessThanEqual", 178>;
-def SPIRV_OC_OpSLessThanEqual                : I32EnumAttrCase<"OpSLessThanEqual", 179>;
-def SPIRV_OC_OpFOrdEqual                     : I32EnumAttrCase<"OpFOrdEqual", 180>;
-def SPIRV_OC_OpFUnordEqual                   : I32EnumAttrCase<"OpFUnordEqual", 181>;
-def SPIRV_OC_OpFOrdNotEqual                  : I32EnumAttrCase<"OpFOrdNotEqual", 182>;
-def SPIRV_OC_OpFUnordNotEqual                : I32EnumAttrCase<"OpFUnordNotEqual", 183>;
-def SPIRV_OC_OpFOrdLessThan                  : I32EnumAttrCase<"OpFOrdLessThan", 184>;
-def SPIRV_OC_OpFUnordLessThan                : I32EnumAttrCase<"OpFUnordLessThan", 185>;
-def SPIRV_OC_OpFOrdGreaterThan               : I32EnumAttrCase<"OpFOrdGreaterThan", 186>;
-def SPIRV_OC_OpFUnordGreaterThan             : I32EnumAttrCase<"OpFUnordGreaterThan", 187>;
-def SPIRV_OC_OpFOrdLessThanEqual             : I32EnumAttrCase<"OpFOrdLessThanEqual", 188>;
-def SPIRV_OC_OpFUnordLessThanEqual           : I32EnumAttrCase<"OpFUnordLessThanEqual", 189>;
-def SPIRV_OC_OpFOrdGreaterThanEqual          : I32EnumAttrCase<"OpFOrdGreaterThanEqual", 190>;
-def SPIRV_OC_OpFUnordGreaterThanEqual        : I32EnumAttrCase<"OpFUnordGreaterThanEqual", 191>;
-def SPIRV_OC_OpShiftRightLogical             : I32EnumAttrCase<"OpShiftRightLogical", 194>;
-def SPIRV_OC_OpShiftRightArithmetic          : I32EnumAttrCase<"OpShiftRightArithmetic", 195>;
-def SPIRV_OC_OpShiftLeftLogical              : I32EnumAttrCase<"OpShiftLeftLogical", 196>;
-def SPIRV_OC_OpBitwiseOr                     : I32EnumAttrCase<"OpBitwiseOr", 197>;
-def SPIRV_OC_OpBitwiseXor                    : I32EnumAttrCase<"OpBitwiseXor", 198>;
-def SPIRV_OC_OpBitwiseAnd                    : I32EnumAttrCase<"OpBitwiseAnd", 199>;
-def SPIRV_OC_OpNot                           : I32EnumAttrCase<"OpNot", 200>;
-def SPIRV_OC_OpBitFieldInsert                : I32EnumAttrCase<"OpBitFieldInsert", 201>;
-def SPIRV_OC_OpBitFieldSExtract              : I32EnumAttrCase<"OpBitFieldSExtract", 202>;
-def SPIRV_OC_OpBitFieldUExtract              : I32EnumAttrCase<"OpBitFieldUExtract", 203>;
-def SPIRV_OC_OpBitReverse                    : I32EnumAttrCase<"OpBitReverse", 204>;
-def SPIRV_OC_OpBitCount                      : I32EnumAttrCase<"OpBitCount", 205>;
-def SPIRV_OC_OpEmitVertex                    : I32EnumAttrCase<"OpEmitVertex", 218>;
-def SPIRV_OC_OpEndPrimitive                  : I32EnumAttrCase<"OpEndPrimitive", 219>;
-def SPIRV_OC_OpControlBarrier                : I32EnumAttrCase<"OpControlBarrier", 224>;
-def SPIRV_OC_OpMemoryBarrier                 : I32EnumAttrCase<"OpMemoryBarrier", 225>;
-def SPIRV_OC_OpAtomicExchange                : I32EnumAttrCase<"OpAtomicExchange", 229>;
-def SPIRV_OC_OpAtomicCompareExchange         : I32EnumAttrCase<"OpAtomicCompareExchange", 230>;
-def SPIRV_OC_OpAtomicCompareExchangeWeak     : I32EnumAttrCase<"OpAtomicCompareExchangeWeak", 231>;
-def SPIRV_OC_OpAtomicIIncrement              : I32EnumAttrCase<"OpAtomicIIncrement", 232>;
-def SPIRV_OC_OpAtomicIDecrement              : I32EnumAttrCase<"OpAtomicIDecrement", 233>;
-def SPIRV_OC_OpAtomicIAdd                    : I32EnumAttrCase<"OpAtomicIAdd", 234>;
-def SPIRV_OC_OpAtomicISub                    : I32EnumAttrCase<"OpAtomicISub", 235>;
-def SPIRV_OC_OpAtomicSMin                    : I32EnumAttrCase<"OpAtomicSMin", 236>;
-def SPIRV_OC_OpAtomicUMin                    : I32EnumAttrCase<"OpAtomicUMin", 237>;
-def SPIRV_OC_OpAtomicSMax                    : I32EnumAttrCase<"OpAtomicSMax", 238>;
-def SPIRV_OC_OpAtomicUMax                    : I32EnumAttrCase<"OpAtomicUMax", 239>;
-def SPIRV_OC_OpAtomicAnd                     : I32EnumAttrCase<"OpAtomicAnd", 240>;
-def SPIRV_OC_OpAtomicOr                      : I32EnumAttrCase<"OpAtomicOr", 241>;
-def SPIRV_OC_OpAtomicXor                     : I32EnumAttrCase<"OpAtomicXor", 242>;
-def SPIRV_OC_OpPhi                           : I32EnumAttrCase<"OpPhi", 245>;
-def SPIRV_OC_OpLoopMerge                     : I32EnumAttrCase<"OpLoopMerge", 246>;
-def SPIRV_OC_OpSelectionMerge                : I32EnumAttrCase<"OpSelectionMerge", 247>;
-def SPIRV_OC_OpLabel                         : I32EnumAttrCase<"OpLabel", 248>;
-def SPIRV_OC_OpBranch                        : I32EnumAttrCase<"OpBranch", 249>;
-def SPIRV_OC_OpBranchConditional             : I32EnumAttrCase<"OpBranchConditional", 250>;
-def SPIRV_OC_OpKill                          : I32EnumAttrCase<"OpKill", 252>;
-def SPIRV_OC_OpReturn                        : I32EnumAttrCase<"OpReturn", 253>;
-def SPIRV_OC_OpReturnValue                   : I32EnumAttrCase<"OpReturnValue", 254>;
-def SPIRV_OC_OpUnreachable                   : I32EnumAttrCase<"OpUnreachable", 255>;
-def SPIRV_OC_OpGroupBroadcast                : I32EnumAttrCase<"OpGroupBroadcast", 263>;
-def SPIRV_OC_OpGroupIAdd                     : I32EnumAttrCase<"OpGroupIAdd", 264>;
-def SPIRV_OC_OpGroupFAdd                     : I32EnumAttrCase<"OpGroupFAdd", 265>;
-def SPIRV_OC_OpGroupFMin                     : I32EnumAttrCase<"OpGroupFMin", 266>;
-def SPIRV_OC_OpGroupUMin                     : I32EnumAttrCase<"OpGroupUMin", 267>;
-def SPIRV_OC_OpGroupSMin                     : I32EnumAttrCase<"OpGroupSMin", 268>;
-def SPIRV_OC_OpGroupFMax                     : I32EnumAttrCase<"OpGroupFMax", 269>;
-def SPIRV_OC_OpGroupUMax                     : I32EnumAttrCase<"OpGroupUMax", 270>;
-def SPIRV_OC_OpGroupSMax                     : I32EnumAttrCase<"OpGroupSMax", 271>;
-def SPIRV_OC_OpNoLine                        : I32EnumAttrCase<"OpNoLine", 317>;
-def SPIRV_OC_OpModuleProcessed               : I32EnumAttrCase<"OpModuleProcessed", 330>;
-def SPIRV_OC_OpGroupNonUniformElect          : I32EnumAttrCase<"OpGroupNonUniformElect", 333>;
-def SPIRV_OC_OpGroupNonUniformBroadcast      : I32EnumAttrCase<"OpGroupNonUniformBroadcast", 337>;
-def SPIRV_OC_OpGroupNonUniformBallot         : I32EnumAttrCase<"OpGroupNonUniformBallot", 339>;
-def SPIRV_OC_OpGroupNonUniformBallotBitCount : I32EnumAttrCase<"OpGroupNonUniformBallotBitCount", 342>;
-def SPIRV_OC_OpGroupNonUniformBallotFindLSB  : I32EnumAttrCase<"OpGroupNonUniformBallotFindLSB", 343>;
-def SPIRV_OC_OpGroupNonUniformBallotFindMSB  : I32EnumAttrCase<"OpGroupNonUniformBallotFindMSB", 344>;
-def SPIRV_OC_OpGroupNonUniformShuffle        : I32EnumAttrCase<"OpGroupNonUniformShuffle", 345>;
-def SPIRV_OC_OpGroupNonUniformShuffleXor     : I32EnumAttrCase<"OpGroupNonUniformShuffleXor", 346>;
-def SPIRV_OC_OpGroupNonUniformShuffleUp      : I32EnumAttrCase<"OpGroupNonUniformShuffleUp", 347>;
-def SPIRV_OC_OpGroupNonUniformShuffleDown    : I32EnumAttrCase<"OpGroupNonUniformShuffleDown", 348>;
-def SPIRV_OC_OpGroupNonUniformIAdd           : I32EnumAttrCase<"OpGroupNonUniformIAdd", 349>;
-def SPIRV_OC_OpGroupNonUniformFAdd           : I32EnumAttrCase<"OpGroupNonUniformFAdd", 350>;
-def SPIRV_OC_OpGroupNonUniformIMul           : I32EnumAttrCase<"OpGroupNonUniformIMul", 351>;
-def SPIRV_OC_OpGroupNonUniformFMul           : I32EnumAttrCase<"OpGroupNonUniformFMul", 352>;
-def SPIRV_OC_OpGroupNonUniformSMin           : I32EnumAttrCase<"OpGroupNonUniformSMin", 353>;
-def SPIRV_OC_OpGroupNonUniformUMin           : I32EnumAttrCase<"OpGroupNonUniformUMin", 354>;
-def SPIRV_OC_OpGroupNonUniformFMin           : I32EnumAttrCase<"OpGroupNonUniformFMin", 355>;
-def SPIRV_OC_OpGroupNonUniformSMax           : I32EnumAttrCase<"OpGroupNonUniformSMax", 356>;
-def SPIRV_OC_OpGroupNonUniformUMax           : I32EnumAttrCase<"OpGroupNonUniformUMax", 357>;
-def SPIRV_OC_OpGroupNonUniformFMax           : I32EnumAttrCase<"OpGroupNonUniformFMax", 358>;
-def SPIRV_OC_OpGroupNonUniformBitwiseAnd     : I32EnumAttrCase<"OpGroupNonUniformBitwiseAnd", 359>;
-def SPIRV_OC_OpGroupNonUniformBitwiseOr      : I32EnumAttrCase<"OpGroupNonUniformBitwiseOr", 360>;
-def SPIRV_OC_OpGroupNonUniformBitwiseXor     : I32EnumAttrCase<"OpGroupNonUniformBitwiseXor", 361>;
-def SPIRV_OC_OpGroupNonUniformLogicalAnd     : I32EnumAttrCase<"OpGroupNonUniformLogicalAnd", 362>;
-def SPIRV_OC_OpGroupNonUniformLogicalOr      : I32EnumAttrCase<"OpGroupNonUniformLogicalOr", 363>;
-def SPIRV_OC_OpGroupNonUniformLogicalXor     : I32EnumAttrCase<"OpGroupNonUniformLogicalXor", 364>;
-def SPIRV_OC_OpSubgroupBallotKHR             : I32EnumAttrCase<"OpSubgroupBallotKHR", 4421>;
-def SPIRV_OC_OpSDot                          : I32EnumAttrCase<"OpSDot", 4450>;
-def SPIRV_OC_OpUDot                          : I32EnumAttrCase<"OpUDot", 4451>;
-def SPIRV_OC_OpSUDot                         : I32EnumAttrCase<"OpSUDot", 4452>;
-def SPIRV_OC_OpSDotAccSat                    : I32EnumAttrCase<"OpSDotAccSat", 4453>;
-def SPIRV_OC_OpUDotAccSat                    : I32EnumAttrCase<"OpUDotAccSat", 4454>;
-def SPIRV_OC_OpSUDotAccSat                   : I32EnumAttrCase<"OpSUDotAccSat", 4455>;
-def SPIRV_OC_OpTypeCooperativeMatrixKHR      : I32EnumAttrCase<"OpTypeCooperativeMatrixKHR", 4456>;
-def SPIRV_OC_OpCooperativeMatrixLoadKHR      : I32EnumAttrCase<"OpCooperativeMatrixLoadKHR", 4457>;
-def SPIRV_OC_OpCooperativeMatrixStoreKHR     : I32EnumAttrCase<"OpCooperativeMatrixStoreKHR", 4458>;
-def SPIRV_OC_OpCooperativeMatrixMulAddKHR    : I32EnumAttrCase<"OpCooperativeMatrixMulAddKHR", 4459>;
-def SPIRV_OC_OpCooperativeMatrixLengthKHR    : I32EnumAttrCase<"OpCooperativeMatrixLengthKHR", 4460>;
-def SPIRV_OC_OpEmitMeshTasksEXT              : I32EnumAttrCase<"OpEmitMeshTasksEXT", 5294>;
-def SPIRV_OC_OpSetMeshOutputsEXT             : I32EnumAttrCase<"OpSetMeshOutputsEXT", 5295>;
-def SPIRV_OC_OpSubgroupBlockReadINTEL        : I32EnumAttrCase<"OpSubgroupBlockReadINTEL", 5575>;
-def SPIRV_OC_OpSubgroupBlockWriteINTEL       : I32EnumAttrCase<"OpSubgroupBlockWriteINTEL", 5576>;
-def SPIRV_OC_OpAssumeTrueKHR                 : I32EnumAttrCase<"OpAssumeTrueKHR", 5630>;
-def SPIRV_OC_OpAtomicFAddEXT                 : I32EnumAttrCase<"OpAtomicFAddEXT", 6035>;
-def SPIRV_OC_OpConvertFToBF16INTEL           : I32EnumAttrCase<"OpConvertFToBF16INTEL", 6116>;
-def SPIRV_OC_OpConvertBF16ToFINTEL           : I32EnumAttrCase<"OpConvertBF16ToFINTEL", 6117>;
-def SPIRV_OC_OpControlBarrierArriveINTEL     : I32EnumAttrCase<"OpControlBarrierArriveINTEL", 6142>;
-def SPIRV_OC_OpControlBarrierWaitINTEL       : I32EnumAttrCase<"OpControlBarrierWaitINTEL", 6143>;
-def SPIRV_OC_OpGroupIMulKHR                  : I32EnumAttrCase<"OpGroupIMulKHR", 6401>;
-def SPIRV_OC_OpGroupFMulKHR                  : I32EnumAttrCase<"OpGroupFMulKHR", 6402>;
+def SPIRV_OC_OpNop                            : I32EnumAttrCase<"OpNop", 0>;
+def SPIRV_OC_OpUndef                          : I32EnumAttrCase<"OpUndef", 1>;
+def SPIRV_OC_OpSourceContinued                : I32EnumAttrCase<"OpSourceContinued", 2>;
+def SPIRV_OC_OpSource                         : I32EnumAttrCase<"OpSource", 3>;
+def SPIRV_OC_OpSourceExtension                : I32EnumAttrCase<"OpSourceExtension", 4>;
+def SPIRV_OC_OpName                           : I32EnumAttrCase<"OpName", 5>;
+def SPIRV_OC_OpMemberName                     : I32EnumAttrCase<"OpMemberName", 6>;
+def SPIRV_OC_OpString                         : I32EnumAttrCase<"OpString", 7>;
+def SPIRV_OC_OpLine                           : I32EnumAttrCase<"OpLine", 8>;
+def SPIRV_OC_OpExtension                      : I32EnumAttrCase<"OpExtension", 10>;
+def SPIRV_OC_OpExtInstImport                  : I32EnumAttrCase<"OpExtInstImport", 11>;
+def SPIRV_OC_OpExtInst                        : I32EnumAttrCase<"OpExtInst", 12>;
+def SPIRV_OC_OpMemoryModel                    : I32EnumAttrCase<"OpMemoryModel", 14>;
+def SPIRV_OC_OpEntryPoint                     : I32EnumAttrCase<"OpEntryPoint", 15>;
+def SPIRV_OC_OpExecutionMode                  : I32EnumAttrCase<"OpExecutionMode", 16>;
+def SPIRV_OC_OpCapability                     : I32EnumAttrCase<"OpCapability", 17>;
+def SPIRV_OC_OpTypeVoid                       : I32EnumAttrCase<"OpTypeVoid", 19>;
+def SPIRV_OC_OpTypeBool                       : I32EnumAttrCase<"OpTypeBool", 20>;
+def SPIRV_OC_OpTypeInt                        : I32EnumAttrCase<"OpTypeInt", 21>;
+def SPIRV_OC_OpTypeFloat                      : I32EnumAttrCase<"OpTypeFloat", 22>;
+def SPIRV_OC_OpTypeVector                     : I32EnumAttrCase<"OpTypeVector", 23>;
+def SPIRV_OC_OpTypeMatrix                     : I32EnumAttrCase<"OpTypeMatrix", 24>;
+def SPIRV_OC_OpTypeImage                      : I32EnumAttrCase<"OpTypeImage", 25>;
+def SPIRV_OC_OpTypeSampledImage               : I32EnumAttrCase<"OpTypeSampledImage", 27>;
+def SPIRV_OC_OpTypeArray                      : I32EnumAttrCase<"OpTypeArray", 28>;
+def SPIRV_OC_OpTypeRuntimeArray               : I32EnumAttrCase<"OpTypeRuntimeArray", 29>;
+def SPIRV_OC_OpTypeStruct                     : I32EnumAttrCase<"OpTypeStruct", 30>;
+def SPIRV_OC_OpTypePointer                    : I32EnumAttrCase<"OpTypePointer", 32>;
+def SPIRV_OC_OpTypeFunction                   : I32EnumAttrCase<"OpTypeFunction", 33>;
+def SPIRV_OC_OpTypeForwardPointer             : I32EnumAttrCase<"OpTypeForwardPointer", 39>;
+def SPIRV_OC_OpConstantTrue                   : I32EnumAttrCase<"OpConstantTrue", 41>;
+def SPIRV_OC_OpConstantFalse                  : I32EnumAttrCase<"OpConstantFalse", 42>;
+def SPIRV_OC_OpConstant                       : I32EnumAttrCase<"OpConstant", 43>;
+def SPIRV_OC_OpConstantComposite              : I32EnumAttrCase<"OpConstantComposite", 44>;
+def SPIRV_OC_OpConstantNull                   : I32EnumAttrCase<"OpConstantNull", 46>;
+def SPIRV_OC_OpSpecConstantTrue               : I32EnumAttrCase<"OpSpecConstantTrue", 48>;
+def SPIRV_OC_OpSpecConstantFalse              : I32EnumAttrCase<"OpSpecConstantFalse", 49>;
+def SPIRV_OC_OpSpecConstant                   : I32EnumAttrCase<"OpSpecConstant", 50>;
+def SPIRV_OC_OpSpecConstantComposite          : I32EnumAttrCase<"OpSpecConstantComposite", 51>;
+def SPIRV_OC_OpSpecConstantOp                 : I32EnumAttrCase<"OpSpecConstantOp", 52>;
+def SPIRV_OC_OpFunction                       : I32EnumAttrCase<"OpFunction", 54>;
+def SPIRV_OC_OpFunctionParameter              : I32EnumAttrCase<"OpFunctionParameter", 55>;
+def SPIRV_OC_OpFunctionEnd                    : I32EnumAttrCase<"OpFunctionEnd", 56>;
+def SPIRV_OC_OpFunctionCall                   : I32EnumAttrCase<"OpFunctionCall", 57>;
+def SPIRV_OC_OpVariable                       : I32EnumAttrCase<"OpVariable", 59>;
+def SPIRV_OC_OpLoad                           : I32EnumAttrCase<"OpLoad", 61>;
+def SPIRV_OC_OpStore                          : I32EnumAttrCase<"OpStore", 62>;
+def SPIRV_OC_OpCopyMemory                     : I32EnumAttrCase<"OpCopyMemory", 63>;
+def SPIRV_OC_OpAccessChain                    : I32EnumAttrCase<"OpAccessChain", 65>;
+def SPIRV_OC_OpPtrAccessChain                 : I32EnumAttrCase<"OpPtrAccessChain", 67>;
+def SPIRV_OC_OpInBoundsPtrAccessChain         : I32EnumAttrCase<"OpInBoundsPtrAccessChain", 70>;
+def SPIRV_OC_OpDecorate                       : I32EnumAttrCase<"OpDecorate", 71>;
+def SPIRV_OC_OpMemberDecorate                 : I32EnumAttrCase<"OpMemberDecorate", 72>;
+def SPIRV_OC_OpVectorExtractDynamic           : I32EnumAttrCase<"OpVectorExtractDynamic", 77>;
+def SPIRV_OC_OpVectorInsertDynamic            : I32EnumAttrCase<"OpVectorInsertDynamic", 78>;
+def SPIRV_OC_OpVectorShuffle                  : I32EnumAttrCase<"OpVectorShuffle", 79>;
+def SPIRV_OC_OpCompositeConstruct             : I32EnumAttrCase<"OpCompositeConstruct", 80>;
+def SPIRV_OC_OpCompositeExtract               : I32EnumAttrCase<"OpCompositeExtract", 81>;
+def SPIRV_OC_OpCompositeInsert                : I32EnumAttrCase<"OpCompositeInsert", 82>;
+def SPIRV_OC_OpTranspose                      : I32EnumAttrCase<"OpTranspose", 84>;
+def SPIRV_OC_OpImageSampleImplicitLod         : I32EnumAttrCase<"OpImageSampleImplicitLod", 87>;
+def SPIRV_OC_OpImageSampleExplicitLod         : I32EnumAttrCase<"OpImageSampleExplicitLod", 88>;
+def SPIRV_OC_OpImageSampleProjDrefImplicitLod : I32EnumAttrCase<"OpImageSampleProjDrefImplicitLod", 93>;
+def SPIRV_OC_OpImageDrefGather                : I32EnumAttrCase<"OpImageDrefGather", 97>;
+def SPIRV_OC_OpImageWrite                     : I32EnumAttrCase<"OpImageWrite", 99>;
+def SPIRV_OC_OpImage                          : I32EnumAttrCase<"OpImage", 100>;
+def SPIRV_OC_OpImageQuerySize                 : I32EnumAttrCase<"OpImageQuerySize", 104>;
+def SPIRV_OC_OpConvertFToU                    : I32EnumAttrCase<"OpConvertFToU", 109>;
+def SPIRV_OC_OpConvertFToS                    : I32EnumAttrCase<"OpConvertFToS", 110>;
+def SPIRV_OC_OpConvertSToF                    : I32EnumAttrCase<"OpConvertSToF", 111>;
+def SPIRV_OC_OpConvertUToF                    : I32EnumAttrCase<"OpConvertUToF", 112>;
+def SPIRV_OC_OpUConvert                       : I32EnumAttrCase<"OpUConvert", 113>;
+def SPIRV_OC_OpSConvert                       : I32EnumAttrCase<"OpSConvert", 114>;
+def SPIRV_OC_OpFConvert                       : I32EnumAttrCase<"OpFConvert", 115>;
+def SPIRV_OC_OpConvertPtrToU                  : I32EnumAttrCase<"OpConvertPtrToU", 117>;
+def SPIRV_OC_OpConvertUToPtr                  : I32EnumAttrCase<"OpConvertUToPtr", 120>;
+def SPIRV_OC_OpPtrCastToGeneric               : I32EnumAttrCase<"OpPtrCastToGeneric", 121>;
+def SPIRV_OC_OpGenericCastToPtr               : I32EnumAttrCase<"OpGenericCastToPtr", 122>;
+def SPIRV_OC_OpGenericCastToPtrExplicit       : I32EnumAttrCase<"OpGenericCastToPtrExplicit", 123>;
+def SPIRV_OC_OpBitcast                        : I32EnumAttrCase<"OpBitcast", 124>;
+def SPIRV_OC_OpSNegate                        : I32EnumAttrCase<"OpSNegate", 126>;
+def SPIRV_OC_OpFNegate                        : I32EnumAttrCase<"OpFNegate", 127>;
+def SPIRV_OC_OpIAdd                           : I32EnumAttrCase<"OpIAdd", 128>;
+def SPIRV_OC_OpFAdd                           : I32EnumAttrCase<"OpFAdd", 129>;
+def SPIRV_OC_OpISub                           : I32EnumAttrCase<"OpISub", 130>;
+def SPIRV_OC_OpFSub                           : I32EnumAttrCase<"OpFSub", 131>;
+def SPIRV_OC_OpIMul                           : I32EnumAttrCase<"OpIMul", 132>;
+def SPIRV_OC_OpFMul                           : I32EnumAttrCase<"OpFMul", 133>;
+def SPIRV_OC_OpUDiv                           : I32EnumAttrCase<"OpUDiv", 134>;
+def SPIRV_OC_OpSDiv                           : I32EnumAttrCase<"OpSDiv", 135>;
+def SPIRV_OC_OpFDiv                           : I32EnumAttrCase<"OpFDiv", 136>;
+def SPIRV_OC_OpUMod                           : I32EnumAttrCase<"OpUMod", 137>;
+def SPIRV_OC_OpSRem                           : I32EnumAttrCase<"OpSRem", 138>;
+def SPIRV_OC_OpSMod                           : I32EnumAttrCase<"OpSMod", 139>;
+def SPIRV_OC_OpFRem                           : I32EnumAttrCase<"OpFRem", 140>;
+def SPIRV_OC_OpFMod                           : I32EnumAttrCase<"OpFMod", 141>;
+def SPIRV_OC_OpVectorTimesScalar              : I32EnumAttrCase<"OpVectorTimesScalar", 142>;
+def SPIRV_OC_OpMatrixTimesScalar              : I32EnumAttrCase<"OpMatrixTimesScalar", 143>;
+def SPIRV_OC_OpVectorTimesMatrix              : I32EnumAttrCase<"OpVectorTimesMatrix", 144>;
+def SPIRV_OC_OpMatrixTimesVector              : I32EnumAttrCase<"OpMatrixTimesVector", 145>;
+def SPIRV_OC_OpMatrixTimesMatrix              : I32EnumAttrCase<"OpMatrixTimesMatrix", 146>;
+def SPIRV_OC_OpDot                            : I32EnumAttrCase<"OpDot", 148>;
+def SPIRV_OC_OpIAddCarry                      : I32EnumAttrCase<"OpIAddCarry", 149>;
+def SPIRV_OC_OpISubBorrow                     : I32EnumAttrCase<"OpISubBorrow", 150>;
+def SPIRV_OC_OpUMulExtended                   : I32EnumAttrCase<"OpUMulExtended", 151>;
+def SPIRV_OC_OpSMulExtended                   : I32EnumAttrCase<"OpSMulExtended", 152>;
+def SPIRV_OC_OpIsNan                          : I32EnumAttrCase<"OpIsNan", 156>;
+def SPIRV_OC_OpIsInf                          : I32EnumAttrCase<"OpIsInf", 157>;
+def SPIRV_OC_OpOrdered                        : I32EnumAttrCase<"OpOrdered", 162>;
+def SPIRV_OC_OpUnordered                      : I32EnumAttrCase<"OpUnordered", 163>;
+def SPIRV_OC_OpLogicalEqual                   : I32EnumAttrCase<"OpLogicalEqual", 164>;
+def SPIRV_OC_OpLogicalNotEqual                : I32EnumAttrCase<"OpLogicalNotEqual", 165>;
+def SPIRV_OC_OpLogicalOr                      : I32EnumAttrCase<"OpLogicalOr", 166>;
+def SPIRV_OC_OpLogicalAnd                     : I32EnumAttrCase<"OpLogicalAnd", 167>;
+def SPIRV_OC_OpLogicalNot                     : I32EnumAttrCase<"OpLogicalNot", 168>;
+def SPIRV_OC_OpSelect                         : I32EnumAttrCase<"OpSelect", 169>;
+def SPIRV_OC_OpIEqual                         : I32EnumAttrCase<"OpIEqual", 170>;
+def SPIRV_OC_OpINotEqual                      : I32EnumAttrCase<"OpINotEqual", 171>;
+def SPIRV_OC_OpUGreaterThan                   : I32EnumAttrCase<"OpUGreaterThan", 172>;
+def SPIRV_OC_OpSGreaterThan                   : I32EnumAttrCase<"OpSGreaterThan", 173>;
+def SPIRV_OC_OpUGreaterThanEqual              : I32EnumAttrCase<"OpUGreaterThanEqual", 174>;
+def SPIRV_OC_OpSGreaterThanEqual              : I32EnumAttrCase<"OpSGreaterThanEqual", 175>;
+def SPIRV_OC_OpULessThan                      : I32EnumAttrCase<"OpULessThan", 176>;
+def SPIRV_OC_OpSLessThan                      : I32EnumAttrCase<"OpSLessThan", 177>;
+def SPIRV_OC_OpULessThanEqual                 : I32EnumAttrCase<"OpULessThanEqual", 178>;
+def SPIRV_OC_OpSLessThanEqual                 : I32EnumAttrCase<"OpSLessThanEqual", 179>;
+def SPIRV_OC_OpFOrdEqual                      : I32EnumAttrCase<"OpFOrdEqual", 180>;
+def SPIRV_OC_OpFUnordEqual                    : I32EnumAttrCase<"OpFUnordEqual", 181>;
+def SPIRV_OC_OpFOrdNotEqual                   : I32EnumAttrCase<"OpFOrdNotEqual", 182>;
+def SPIRV_OC_OpFUnordNotEqual                 : I32EnumAttrCase<"OpFUnordNotEqual", 183>;
+def SPIRV_OC_OpFOrdLessThan                   : I32EnumAttrCase<"OpFOrdLessThan", 184>;
+def SPIRV_OC_OpFUnordLessThan                 : I32EnumAttrCase<"OpFUnordLessThan", 185>;
+def SPIRV_OC_OpFOrdGreaterThan                : I32EnumAttrCase<"OpFOrdGreaterThan", 186>;
+def SPIRV_OC_OpFUnordGreaterThan              : I32EnumAttrCase<"OpFUnordGreaterThan", 187>;
+def SPIRV_OC_OpFOrdLessThanEqual              : I32EnumAttrCase<"OpFOrdLessThanEqual", 188>;
+def SPIRV_OC_OpFUnordLessThanEqual            : I32EnumAttrCase<"OpFUnordLessThanEqual", 189>;
+def SPIRV_OC_OpFOrdGreaterThanEqual           : I32EnumAttrCase<"OpFOrdGreaterThanEqual", 190>;
+def SPIRV_OC_OpFUnordGreaterThanEqual         : I32EnumAttrCase<"OpFUnordGreaterThanEqual", 191>;
+def SPIRV_OC_OpShiftRightLogical              : I32EnumAttrCase<"OpShiftRightLogical", 194>;
+def SPIRV_OC_OpShiftRightArithmetic           : I32EnumAttrCase<"OpShiftRightArithmetic", 195>;
+def SPIRV_OC_OpShiftLeftLogical               : I32EnumAttrCase<"OpShiftLeftLogical", 196>;
+def SPIRV_OC_OpBitwiseOr                      : I32EnumAttrCase<"OpBitwiseOr", 197>;
+def SPIRV_OC_OpBitwiseXor                     : I32EnumAttrCase<"OpBitwiseXor", 198>;
+def SPIRV_OC_OpBitwiseAnd                     : I32EnumAttrCase<"OpBitwiseAnd", 199>;
+def SPIRV_OC_OpNot                            : I32EnumAttrCase<"OpNot", 200>;
+def SPIRV_OC_OpBitFieldInsert                 : I32EnumAttrCase<"OpBitFieldInsert", 201>;
+def SPIRV_OC_OpBitFieldSExtract               : I32EnumAttrCase<"OpBitFieldSExtract", 202>;
+def SPIRV_OC_OpBitFieldUExtract               : I32EnumAttrCase<"OpBitFieldUExtract", 203>;
+def SPIRV_OC_OpBitReverse                     : I32EnumAttrCase<"OpBitReverse", 204>;
+def SPIRV_OC_OpBitCount                       : I32EnumAttrCase<"OpBitCount", 205>;
+def SPIRV_OC_OpEmitVertex                     : I32EnumAttrCase<"OpEmitVertex", 218>;
+def SPIRV_OC_OpEndPrimitive                   : I32EnumAttrCase<"OpEndPrimitive", 219>;
+def SPIRV_OC_OpControlBarrier                 : I32EnumAttrCase<"OpControlBarrier", 224>;
+def SPIRV_OC_OpMemoryBarrier                  : I32EnumAttrCase<"OpMemoryBarrier", 225>;
+def SPIRV_OC_OpAtomicExchange                 : I32EnumAttrCase<"OpAtomicExchange", 229>;
+def SPIRV_OC_OpAtomicCompareExchange          : I32EnumAttrCase<"OpAtomicCompareExchange", 230>;
+def SPIRV_OC_OpAtomicCompareExchangeWeak      : I32EnumAttrCase<"OpAtomicCompareExchangeWeak", 231>;
+def SPIRV_OC_OpAtomicIIncrement               : I32EnumAttrCase<"OpAtomicIIncrement", 232>;
+def SPIRV_OC_OpAtomicIDecrement               : I32EnumAttrCase<"OpAtomicIDecrement", 233>;
+def SPIRV_OC_OpAtomicIAdd                     : I32EnumAttrCase<"OpAtomicIAdd", 234>;
+def SPIRV_OC_OpAtomicISub                     : I32EnumAttrCase<"OpAtomicISub", 235>;
+def SPIRV_OC_OpAtomicSMin                     : I32EnumAttrCase<"OpAtomicSMin", 236>;
+def SPIRV_OC_OpAtomicUMin                     : I32EnumAttrCase<"OpAtomicUMin", 237>;
+def SPIRV_OC_OpAtomicSMax                     : I32EnumAttrCase<"OpAtomicSMax", 238>;
+def SPIRV_OC_OpAtomicUMax                     : I32EnumAttrCase<"OpAtomicUMax", 239>;
+def SPIRV_OC_OpAtomicAnd                      : I32EnumAttrCase<"OpAtomicAnd", 240>;
+def SPIRV_OC_OpAtomicOr                       : I32EnumAttrCase<"OpAtomicOr", 241>;
+def SPIRV_OC_OpAtomicXor                      : I32EnumAttrCase<"OpAtomicXor", 242>;
+def SPIRV_OC_OpPhi                            : I32EnumAttrCase<"OpPhi", 245>;
+def SPIRV_OC_OpLoopMerge                      : I32EnumAttrCase<"OpLoopMerge", 246>;
+def SPIRV_OC_OpSelectionMerge                 : I32EnumAttrCase<"OpSelectionMerge", 247>;
+def SPIRV_OC_OpLabel                          : I32EnumAttrCase<"OpLabel", 248>;
+def SPIRV_OC_OpBranch                         : I32EnumAttrCase<"OpBranch", 249>;
+def SPIRV_OC_OpBranchConditional              : I32EnumAttrCase<"OpBranchConditional", 250>;
+def SPIRV_OC_OpKill                           : I32EnumAttrCase<"OpKill", 252>;
+def SPIRV_OC_OpReturn                         : I32EnumAttrCase<"OpReturn", 253>;
+def SPIRV_OC_OpReturnValue                    : I32EnumAttrCase<"OpReturnValue", 254>;
+def SPIRV_OC_OpUnreachable                    : I32EnumAttrCase<"OpUnreachable", 255>;
+def SPIRV_OC_OpGroupBroadcast                 : I32EnumAttrCase<"OpGroupBroadcast", 263>;
+def SPIRV_OC_OpGroupIAdd                      : I32EnumAttrCase<"OpGroupIAdd", 264>;
+def SPIRV_OC_OpGroupFAdd                      : I32EnumAttrCase<"OpGroupFAdd", 265>;
+def SPIRV_OC_OpGroupFMin                      : I32EnumAttrCase<"OpGroupFMin", 266>;
+def SPIRV_OC_OpGroupUMin                      : I32EnumAttrCase<"OpGroupUMin", 267>;
+def SPIRV_OC_OpGroupSMin                      : I32EnumAttrCase<"OpGroupSMin", 268>;
+def SPIRV_OC_OpGroupFMax                      : I32EnumAttrCase<"OpGroupFMax", 269>;
+def SPIRV_OC_OpGroupUMax                      : I32EnumAttrCase<"OpGroupUMax", 270>;
+def SPIRV_OC_OpGroupSMax                      : I32EnumAttrCase<"OpGroupSMax", 271>;
+def SPIRV_OC_OpNoLine                         : I32EnumAttrCase<"OpNoLine", 317>;
+def SPIRV_OC_OpModuleProcessed                : I32EnumAttrCase<"OpModuleProcessed", 330>;
+def SPIRV_OC_OpGroupNonUniformElect           : I32EnumAttrCase<"OpGroupNonUniformElect", 333>;
+def SPIRV_OC_OpGroupNonUniformBroadcast       : I32EnumAttrCase<"OpGroupNonUniformBroadcast", 337>;
+def SPIRV_OC_OpGroupNonUniformBallot          : I32EnumAttrCase<"OpGroupNonUniformBallot", 339>;
+def SPIRV_OC_OpGroupNonUniformBallotBitCount  : I32EnumAttrCase<"OpGroupNonUniformBallotBitCount", 342>;
+def SPIRV_OC_OpGroupNonUniformBallotFindLSB   : I32EnumAttrCase<"OpGroupNonUniformBallotFindLSB", 343>;
+def SPIRV_OC_OpGroupNonUniformBallotFindMSB   : I32EnumAttrCase<"OpGroupNonUniformBallotFindMSB", 344>;
+def SPIRV_OC_OpGroupNonUniformShuffle         : I32EnumAttrCase<"OpGroupNonUniformShuffle", 345>;
+def SPIRV_OC_OpGroupNonUniformShuffleXor      : I32EnumAttrCase<"OpGroupNonUniformShuffleXor", 346>;
+def SPIRV_OC_OpGroupNonUniformShuffleUp       : I32EnumAttrCase<"OpGroupNonUniformShuffleUp", 347>;
+def SPIRV_OC_OpGroupNonUniformShuffleDown     : I32EnumAttrCase<"OpGroupNonUniformShuffleDown", 348>;
+def SPIRV_OC_OpGroupNonUniformIAdd            : I32EnumAttrCase<"OpGroupNonUniformIAdd", 349>;
+def SPIRV_OC_OpGroupNonUniformFAdd            : I32EnumAttrCase<"OpGroupNonUniformFAdd", 350>;
+def SPIRV_OC_OpGroupNonUniformIMul            : I32EnumAttrCase<"OpGroupNonUniformIMul", 351>;
+def SPIRV_OC_OpGroupNonUniformFMul            : I32EnumAttrCase<"OpGroupNonUniformFMul", 352>;
+def SPIRV_OC_OpGroupNonUniformSMin            : I32EnumAttrCase<"OpGroupNonUniformSMin", 353>;
+def SPIRV_OC_OpGroupNonUniformUMin            : I32EnumAttrCase<"OpGroupNonUniformUMin", 354>;
+def SPIRV_OC_OpGroupNonUniformFMin            : I32EnumAttrCase<"OpGroupNonUniformFMin", 355>;
+def SPIRV_OC_OpGroupNonUniformSMax            : I32EnumAttrCase<"OpGroupNonUniformSMax", 356>;
+def SPIRV_OC_OpGroupNonUniformUMax            : I32EnumAttrCase<"OpGroupNonUniformUMax", 357>;
+def SPIRV_OC_OpGroupNonUniformFMax            : I32EnumAttrCase<"OpGroupNonUniformFMax", 358>;
+def SPIRV_OC_OpGroupNonUniformBitwiseAnd      : I32EnumAttrCase<"OpGroupNonUniformBitwiseAnd", 359>;
+def SPIRV_OC_OpGroupNonUniformBitwiseOr       : I32EnumAttrCase<"OpGroupNonUniformBitwiseOr", 360>;
+def SPIRV_OC_OpGroupNonUniformBitwiseXor      : I32EnumAttrCase<"OpGroupNonUniformBitwiseXor", 361>;
+def SPIRV_OC_OpGroupNonUniformLogicalAnd      : I32EnumAttrCase<"OpGroupNonUniformLogicalAnd", 362>;
+def SPIRV_OC_OpGroupNonUniformLogicalOr       : I32EnumAttrCase<"OpGroupNonUniformLogicalOr", 363>;
+def SPIRV_OC_OpGroupNonUniformLogicalXor      : I32EnumAttrCase<"OpGroupNonUniformLogicalXor", 364>;
+def SPIRV_OC_OpSubgroupBallotKHR              : I32EnumAttrCase<"OpSubgroupBallotKHR", 4421>;
+def SPIRV_OC_OpSDot                           : I32EnumAttrCase<"OpSDot", 4450>;
+def SPIRV_OC_OpUDot                           : I32EnumAttrCase<"OpUDot", 4451>;
+def SPIRV_OC_OpSUDot                          : I32EnumAttrCase<"OpSUDot", 4452>;
+def SPIRV_OC_OpSDotAccSat                     : I32EnumAttrCase<"OpSDotAccSat", 4453>;
+def SPIRV_OC_OpUDotAccSat                     : I32EnumAttrCase<"OpUDotAccSat", 4454>;
+def SPIRV_OC_OpSUDotAccSat                    : I32EnumAttrCase<"OpSUDotAccSat", 4455>;
+def SPIRV_OC_OpTypeCooperativeMatrixKHR       : I32EnumAttrCase<"OpTypeCooperativeMatrixKHR", 4456>;
+def SPIRV_OC_OpCooperativeMatrixLoadKHR       : I32EnumAttrCase<"OpCooperativeMatrixLoadKHR", 4457>;
+def SPIRV_OC_OpCooperativeMatrixStoreKHR      : I32EnumAttrCase<"OpCooperativeMatrixStoreKHR", 4458>;
+def SPIRV_OC_OpCooperativeMatrixMulAddKHR     : I32EnumAttrCase<"OpCooperativeMatrixMulAddKHR", 4459>;
+def SPIRV_OC_OpCooperativeMatrixLengthKHR     : I32EnumAttrCase<"OpCooperativeMatrixLengthKHR", 4460>;
+def SPIRV_OC_OpEmitMeshTasksEXT               : I32EnumAttrCase<"OpEmitMeshTasksEXT", 5294>;
+def SPIRV_OC_OpSetMeshOutputsEXT              : I32EnumAttrCase<"OpSetMeshOutputsEXT", 5295>;
+def SPIRV_OC_OpSubgroupBlockReadINTEL         : I32EnumAttrCase<"OpSubgroupBlockReadINTEL", 5575>;
+def SPIRV_OC_OpSubgroupBlockWriteINTEL        : I32EnumAttrCase<"OpSubgroupBlockWriteINTEL", 5576>;
+def SPIRV_OC_OpAssumeTrueKHR                  : I32EnumAttrCase<"OpAssumeTrueKHR", 5630>;
+def SPIRV_OC_OpAtomicFAddEXT                  : I32EnumAttrCase<"OpAtomicFAddEXT", 6035>;
+def SPIRV_OC_OpConvertFToBF16INTEL            : I32EnumAttrCase<"OpConvertFToBF16INTEL", 6116>;
+def SPIRV_OC_OpConvertBF16ToFINTEL            : I32EnumAttrCase<"OpConvertBF16ToFINTEL", 6117>;
+def SPIRV_OC_OpControlBarrierArriveINTEL      : I32EnumAttrCase<"OpControlBarrierArriveINTEL", 6142>;
+def SPIRV_OC_OpControlBarrierWaitINTEL        : I32EnumAttrCase<"OpControlBarrierWaitINTEL", 6143>;
+def SPIRV_OC_OpGroupIMulKHR                   : I32EnumAttrCase<"OpGroupIMulKHR", 6401>;
+def SPIRV_OC_OpGroupFMulKHR                   : I32EnumAttrCase<"OpGroupFMulKHR", 6402>;
 
 def SPIRV_OpcodeAttr :
     SPIRV_I32EnumAttr<"Opcode", "valid SPIR-V instructions", "opcode", [
@@ -4535,7 +4538,9 @@ def SPIRV_OpcodeAttr :
       SPIRV_OC_OpMemberDecorate, SPIRV_OC_OpVectorExtractDynamic,
       SPIRV_OC_OpVectorInsertDynamic, SPIRV_OC_OpVectorShuffle,
       SPIRV_OC_OpCompositeConstruct, SPIRV_OC_OpCompositeExtract,
-      SPIRV_OC_OpCompositeInsert, SPIRV_OC_OpTranspose, SPIRV_OC_OpImageDrefGather,
+      SPIRV_OC_OpCompositeInsert, SPIRV_OC_OpTranspose,
+      SPIRV_OC_OpImageSampleImplicitLod, SPIRV_OC_OpImageSampleExplicitLod,
+      SPIRV_OC_OpImageSampleProjDrefImplicitLod, SPIRV_OC_OpImageDrefGather,
       SPIRV_OC_OpImageWrite, SPIRV_OC_OpImage, SPIRV_OC_OpImageQuerySize,
       SPIRV_OC_OpConvertFToU, SPIRV_OC_OpConvertFToS, SPIRV_OC_OpConvertSToF,
       SPIRV_OC_OpConvertUToF, SPIRV_OC_OpUConvert, SPIRV_OC_OpSConvert,

diff  --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVImageOps.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVImageOps.td
index 0cdd7b5e9facc..9999e5cc07b86 100644
--- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVImageOps.td
+++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVImageOps.td
@@ -15,6 +15,7 @@
 #define MLIR_DIALECT_SPIRV_IR_IMAGE_OPS
 
 include "mlir/Dialect/SPIRV/IR/SPIRVBase.td"
+include "mlir/Dialect/SPIRV/Interfaces/SPIRVImageInterfaces.td"
 include "mlir/Interfaces/SideEffectInterfaces.td"
 
 // -----
@@ -48,14 +49,19 @@ class SPIRV_DimIsNot<string operand, list<string> values, string transform="$_se
 
 class SPIRV_NoneOrElementMatchImage<string operand, string image, string transform="$_self"> : PredOpTrait<
   "the " # operand # " component type must match the image sampled type",
-  CPred<"::llvm::isa<NoneType>(cast<ImageType>(" # !subst("$_self", "$" # image # ".getType()", transform) # ").getElementType()) ||"
+  CPred<"::llvm::isa<NoneType>(cast<::mlir::spirv::ImageType>(" # !subst("$_self", "$" # image # ".getType()", transform) # ").getElementType()) ||"
         "(getElementTypeOrSelf($" # operand # ")"
           "=="
-        "cast<ImageType>(" # !subst("$_self", "$" # image # ".getType()", transform) # ").getElementType())"
+        "cast<::mlir::spirv::ImageType>(" # !subst("$_self", "$" # image # ".getType()", transform) # ").getElementType())"
   >
 >;
 
-def SPIRV_SampledImageTransform : StrFunc<"llvm::cast<spirv::SampledImageType>($_self).getImageType()">;
+class SPIRV_ImageOperandIsPresent<string operand, list<string> values> : PredOpTrait<
+  "either " # !interleave(values, " or ") # " image operands must be present",
+  CPred<"::mlir::spirv::bitEnumContainsAny($" # operand # ", " # "::mlir::spirv::ImageOperands::" # !interleave(values, " | ::mlir::spirv::ImageOperands::") # ")">
+>;
+
+def SPIRV_SampledImageTransform : StrFunc<"llvm::cast<::mlir::spirv::SampledImageType>($_self).getImageType()">;
 
 // -----
 
@@ -89,7 +95,7 @@ def SPIRV_ImageDrefGatherOp : SPIRV_Op<"ImageDrefGather",
 
     ```mlir
     %0 = spirv.ImageDrefGather %1, %2, %3 : !spirv.sampled_image<!spirv.image<i32, Dim2D, NoDepth, NonArrayed, SingleSampled, NoSampler, Unknown>>, vector<4xf32>, f32 -> vector<4xi32>
-    %0 = spirv.ImageDrefGather %1, %2, %3 : !spirv.sampled_image<!spirv.image<i32, Dim2D, NoDepth, NonArrayed, SingleSampled, NoSampler, Unknown>>, vector<4xf32>, f32 ["NonPrivateTexel"] -> vector<4xi32>
+    %0 = spirv.ImageDrefGather %1, %2, %3 ["NonPrivateTexel"] : !spirv.sampled_image<!spirv.image<i32, Dim2D, NoDepth, NonArrayed, SingleSampled, NoSampler, Unknown>>, vector<4xf32>, f32 -> vector<4xi32>
     ```
   }];
 
@@ -268,4 +274,214 @@ def SPIRV_ImageOp : SPIRV_Op<"Image",
   let hasVerifier = 0;
 }
 
-#endif // MLIR_DIALECT_SPIRV_IR_GL_OPS
+// -----
+
+def SPIRV_ImageSampleExplicitLodOp : SPIRV_Op<"ImageSampleExplicitLod",
+    [SPIRV_DimIsNot<"sampled_image", ["Buffer"], SPIRV_SampledImageTransform.result>,
+     SPIRV_MSOperandIs<"sampled_image", ["SingleSampled"], SPIRV_SampledImageTransform.result>,
+     SPIRV_NoneOrElementMatchImage<"result", "sampled_image", SPIRV_SampledImageTransform.result>,
+     SPIRV_ImageOperandIsPresent<"image_operands", ["Lod", "Grad"]>,
+     DeclareOpInterfaceMethods<SPIRV_ExplicitLodOpInterface>]> {
+  let summary = "Sample an image using an explicit level of detail.";
+
+  let description = [{
+    Result Type must be a vector of four components of floating-point type
+    or integer type. Its components must be the same as Sampled Type of the
+    underlying OpTypeImage (unless that underlying Sampled Type is
+    OpTypeVoid).
+
+    Sampled Image must be an object whose type is OpTypeSampledImage. Its
+    OpTypeImage must not have a Dim of Buffer. The MS operand of the
+    underlying OpTypeImage must be 0.
+
+    Coordinate must be a scalar or vector of floating-point type or integer
+    type. It contains (u[, v] ... [, array layer]) as needed by the
+    definition of Sampled Image. Unless the Kernel capability is declared,
+    it must be floating point. It may be a vector larger than needed, but
+    all unused components appear after all used components.
+
+    Image Operands encodes what operands follow, as per Image Operands.
+    Either Lod or Grad image operands must be present.
+
+    <!-- End of AutoGen section -->
+
+    #### Example:
+
+    ```mlir
+    %result = spirv.ImageSampleExplicitLod %image, %coord ["Lod"](%lod) :
+      !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Unknown>>,
+      vector<2xf32> (f32) -> vector<4xf32>
+    ```
+  }];
+
+  let arguments = (ins
+    SPIRV_AnySampledImage:$sampled_image,
+    AnyTypeOf<[SPIRV_ScalarOrVectorOf<SPIRV_Float>, SPIRV_ScalarOrVectorOf<SPIRV_Integer>]>:$coordinate,
+    SPIRV_ImageOperandsAttr:$image_operands,
+    Variadic<SPIRV_Type>:$operand_arguments
+  );
+
+  let results = (outs
+    AnyTypeOf<[SPIRV_Vec4<SPIRV_Integer>, SPIRV_Vec4<SPIRV_Float>]>:$result
+  );
+
+  let assemblyFormat = [{
+    $sampled_image `,` $coordinate custom<ImageOperands>($image_operands) ( `,` $operand_arguments^ )? attr-dict
+      `:` type($sampled_image) `,` type($coordinate) ( `,` type($operand_arguments)^ )?
+      `->` type($result)
+  }];
+}
+
+// -----
+
+def SPIRV_ImageSampleImplicitLodOp : SPIRV_Op<"ImageSampleImplicitLod",
+    [SPIRV_DimIsNot<"sampled_image", ["Buffer"], SPIRV_SampledImageTransform.result>,
+     SPIRV_MSOperandIs<"sampled_image", ["SingleSampled"], SPIRV_SampledImageTransform.result>,
+     SPIRV_NoneOrElementMatchImage<"result", "sampled_image", SPIRV_SampledImageTransform.result>,
+     DeclareOpInterfaceMethods<SPIRV_ImplicitLodOpInterface>]> {
+  let summary = "Sample an image with an implicit level of detail.";
+
+  let description = [{
+    An invocation will not execute a dynamic instance of this instruction
+    (X') until all invocations in its derivative group have executed all
+    dynamic instances that are program-ordered before X'.
+
+    Result Type must be a vector of four components of floating-point type
+    or integer type. Its components must be the same as Sampled Type of the
+    underlying OpTypeImage (unless that underlying Sampled Type is
+    OpTypeVoid).
+
+    Sampled Image must be an object whose type is OpTypeSampledImage. Its
+    OpTypeImage must not have a Dim of Buffer. The MS operand of the
+    underlying OpTypeImage must be 0.
+
+    Coordinate must be a scalar or vector of floating-point type. It
+    contains (u[, v] ... [, array layer]) as needed by the definition of
+    Sampled Image. It may be a vector larger than needed, but all unused
+    components appear after all used components.
+
+    Image Operands encodes what operands follow, as per Image Operands.
+
+    This instruction is only valid in the Fragment Execution Model. In
+    addition, it consumes an implicit derivative that can be affected by
+    code motion.
+
+    <!-- End of AutoGen section -->
+
+    #### Example:
+
+    ```mlir
+    %result = spirv.ImageSampleImplicitLod %image, %coord :
+      !spirv.sampled_image<!spirv.image<f32, Cube, NoDepth, NonArrayed, SingleSampled, NeedSampler, Unknown>>,
+      vector<3xf32> -> vector<4xf32>
+    ```
+  }];
+
+  let availability = [
+    MinVersion<SPIRV_V_1_0>,
+    MaxVersion<SPIRV_V_1_6>,
+    Extension<[]>,
+    Capability<[SPIRV_C_Shader]>
+  ];
+
+  let arguments = (ins
+    SPIRV_AnySampledImage:$sampled_image,
+    SPIRV_ScalarOrVectorOf<SPIRV_Float>:$coordinate,
+    OptionalAttr<SPIRV_ImageOperandsAttr>:$image_operands,
+    Variadic<SPIRV_Type>:$operand_arguments
+  );
+
+  let results = (outs
+    AnyTypeOf<[SPIRV_Vec4<SPIRV_Integer>, SPIRV_Vec4<SPIRV_Float>]>:$result
+  );
+
+  let assemblyFormat = [{
+    $sampled_image `,` $coordinate custom<ImageOperands>($image_operands) ( `,` $operand_arguments^ )? attr-dict
+      `:` type($sampled_image) `,` type($coordinate) ( `,` type($operand_arguments)^ )?
+      `->` type($result)
+  }];
+}
+
+// -----
+
+def SPIRV_ImageSampleProjDrefImplicitLodOp : SPIRV_Op<"ImageSampleProjDrefImplicitLod",
+    [SPIRV_DimIsNot<"sampled_image", ["Buffer"], SPIRV_SampledImageTransform.result>,
+     SPIRV_MSOperandIs<"sampled_image", ["SingleSampled"], SPIRV_SampledImageTransform.result>,
+     TypesMatchWith<"type of 'result' matches image type of 'sampled_image'",
+                    "sampled_image", "result",
+                    "::llvm::cast<::mlir::spirv::ImageType>(::llvm::cast<spirv::SampledImageType>($_self).getImageType()).getElementType()">,
+     DeclareOpInterfaceMethods<SPIRV_ImplicitLodOpInterface>]> {
+
+  let summary = [{
+    Sample an image with a project coordinate, doing depth-comparison, with
+    an implicit level of detail.
+  }];
+
+  let description = [{
+    An invocation will not execute a dynamic instance of this instruction
+    (X') until all invocations in its derivative group have executed all
+    dynamic instances that are program-ordered before X'.
+
+    Result Type must be a scalar of integer type or floating-point type. It
+    must be the same as Sampled Type of the underlying OpTypeImage.
+
+    Sampled Image must be an object whose type is OpTypeSampledImage. The
+    Dim operand of the underlying OpTypeImage must be 1D, 2D, 3D, or Rect,
+    and the Arrayed and MS operands must be 0.
+
+    Coordinate must be a vector of floating-point type. It contains (u[,
+    v] [, w], q), as needed by the definition of Sampled Image, with the q
+    component consumed for the projective division. That is, the actual
+    sample coordinate is (u/q [, v/q] [, w/q]), as needed by the definition
+    of Sampled Image. It may be a vector larger than needed, but all unused
+    components appear after all used components.
+
+    Dref/q is the depth-comparison reference value. Dref must be a 32-bit
+    floating-point type scalar.
+
+    Image Operands encodes what operands follow, as per Image Operands.
+
+    This instruction is only valid in the Fragment Execution Model. In
+    addition, it consumes an implicit derivative that can be affected by
+    code motion.
+
+    <!-- End of AutoGen section -->
+
+    #### Example:
+
+    ```mlir
+    %result = spirv.ImageSampleProjDrefImplicitLod %image, %coord, %dref :
+      !spirv.sampled_image<!spirv.image<f32, Dim2D, IsDepth, NonArrayed, SingleSampled, NeedSampler, Unknown>>,
+      vector<4xf16>, f32 -> f32
+    ```
+  }];
+
+  let availability = [
+    MinVersion<SPIRV_V_1_0>,
+    MaxVersion<SPIRV_V_1_6>,
+    Extension<[]>,
+    Capability<[SPIRV_C_Shader]>
+  ];
+
+  let arguments = (ins
+    SPIRV_AnySampledImage:$sampled_image,
+    AnyTypeOf<[SPIRV_ScalarOrVectorOf<SPIRV_Float>, SPIRV_ScalarOrVectorOf<SPIRV_Integer>]>:$coordinate,
+    SPIRV_Float32:$dref,
+    OptionalAttr<SPIRV_ImageOperandsAttr>:$image_operands,
+    Variadic<SPIRV_Type>:$operand_arguments
+  );
+
+  let results = (outs
+    AnyTypeOf<[SPIRV_Integer, SPIRV_Float]>:$result
+  );
+
+  let assemblyFormat = [{
+    $sampled_image `,` $coordinate `,` $dref custom<ImageOperands>($image_operands) ( `,` $operand_arguments^ )? attr-dict
+      `:` type($sampled_image) `,` type($coordinate) `,` type($dref) ( `,` type($operand_arguments)^ )?
+      `->` type($result)
+  }];
+}
+
+// -----
+
+#endif // MLIR_DIALECT_SPIRV_IR_IMAGE_OPS

diff  --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVOps.h b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVOps.h
index f9fc165998b52..2676e921c73fb 100644
--- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVOps.h
+++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVOps.h
@@ -17,6 +17,7 @@
 #include "mlir/Dialect/SPIRV/IR/SPIRVAttributes.h"
 #include "mlir/Dialect/SPIRV/IR/SPIRVOpTraits.h"
 #include "mlir/Dialect/SPIRV/IR/SPIRVTypes.h"
+#include "mlir/Dialect/SPIRV/Interfaces/SPIRVImageInterfaces.h"
 #include "mlir/IR/BuiltinOps.h"
 #include "mlir/IR/OpImplementation.h"
 #include "mlir/Interfaces/CallInterfaces.h"

diff  --git a/mlir/include/mlir/Dialect/SPIRV/Interfaces/CMakeLists.txt b/mlir/include/mlir/Dialect/SPIRV/Interfaces/CMakeLists.txt
new file mode 100644
index 0000000000000..3343882039d84
--- /dev/null
+++ b/mlir/include/mlir/Dialect/SPIRV/Interfaces/CMakeLists.txt
@@ -0,0 +1 @@
+add_mlir_interface(SPIRVImageInterfaces)

diff  --git a/mlir/include/mlir/Dialect/SPIRV/Interfaces/SPIRVImageInterfaces.h b/mlir/include/mlir/Dialect/SPIRV/Interfaces/SPIRVImageInterfaces.h
new file mode 100644
index 0000000000000..ca5a1dcd88171
--- /dev/null
+++ b/mlir/include/mlir/Dialect/SPIRV/Interfaces/SPIRVImageInterfaces.h
@@ -0,0 +1,14 @@
+//===- SPIRVImageInterfaces.h -----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_SPIRV_IMAGE_INTERFACES_H_
+#define MLIR_DIALECT_SPIRV_IMAGE_INTERFACES_H_
+
+#include "mlir/Dialect/SPIRV/Interfaces/SPIRVImageInterfaces.h.inc"
+
+#endif // MLIR_DIALECT_SPIRV_IMAGE_INTERFACES_H_

diff  --git a/mlir/include/mlir/Dialect/SPIRV/Interfaces/SPIRVImageInterfaces.td b/mlir/include/mlir/Dialect/SPIRV/Interfaces/SPIRVImageInterfaces.td
new file mode 100644
index 0000000000000..2b681d9367a4a
--- /dev/null
+++ b/mlir/include/mlir/Dialect/SPIRV/Interfaces/SPIRVImageInterfaces.td
@@ -0,0 +1,89 @@
+//===-- SPIRVImageInterfaces.td - MLIR SPIR-V Image Interfaces ------*- tablegen -*------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===------------------------------------------------------------------------------------===//
+//
+// This file contains interfaces used by image operations. 
+//
+//===------------------------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_SPIRV_IMAGE_INTERFACES
+#define MLIR_DIALECT_SPIRV_IMAGE_INTERFACES
+
+include "mlir/Dialect/SPIRV/IR/SPIRVBase.td"
+
+// -----
+
+def SPIRV_SampleOpInterface : OpInterface<"SamplingOpInterface"> {
+  let description = [{
+    The `SampleOpInterface` defines sampling image operations (`spirv.Image*Sample*`)
+    and provides interface methods to query operands common across all sampling
+    instructions.
+
+    Currently only getters for sampled image and coordinate are provided. The
+    default implementation will work as long as the instruction the interface is
+    attached to uses standard names for the operands: `$sampled_image` and `$coordinate`.
+  }];
+  let cppNamespace = "::mlir::spirv";
+  let methods = [
+    InterfaceMethod<
+      "Get SampledImage of the operation.",
+      "::mlir::TypedValue<::mlir::Type>", "getSampledImage", (ins), [{
+        return $_op.getSampledImage();
+    }]>,
+    InterfaceMethod<
+      "Get Coordinate of the operation.",
+      "::mlir::TypedValue<::mlir::Type>", "getCoordinate", (ins), [{
+        return $_op.getCoordinate();
+    }]>
+  ];
+}
+
+// -----
+
+def SPIRV_ExplicitLodOpInterface : OpInterface<"ExplicitLodOpInterface", [SPIRV_SampleOpInterface]> {
+  let description = [{
+    The `ExplicitLodOpInterface` defines explicit sampling lod operations (`spirv.*ExplicitLod`). Currently
+    the interface is only used to check whether the instruction is an explicit lod.
+  }];
+  let cppNamespace = "::mlir::spirv";
+}
+
+// -----
+
+def SPIRV_ImplicitLodOpInterface : OpInterface<"ImplicitLodOpInterface", [SPIRV_SampleOpInterface]> {
+  let description = [{
+    The `ImplicitLodOpInterface` defines implicit sampling lod operations (`spirv.*ImplicitLod`). Currently
+    the interface is only used to check whether the instruction is an implicit lod.
+  }];
+  let cppNamespace = "::mlir::spirv";
+}
+
+// -----
+
+def SPIRV_FetchOpInterface : OpInterface<"FetchOpInterface"> {
+  let description = [{
+    The `FetchOpInterface` defines fetch image operations (`spirv.ImageFetch` and
+    `spirv.ImageSpareFetch`) and provides interface methods to query operands common
+    across all fetch instructions.
+
+    Currently only a getter for image is provided. The default implementation
+    will work as long as the instruction the interface is attached to uses
+    standard names for the operands: `$image`.
+  }];
+  let cppNamespace = "::mlir::spirv";
+  let methods = [
+    InterfaceMethod<
+      "Get Image of the operation.",
+      "::mlir::TypedValue<::mlir::Type>", "getImage", (ins), [{
+        return $_op.getImage();
+    }]>
+  ];
+}
+
+// -----
+
+#endif // MLIR_DIALECT_SPIRV_IMAGE_INTERFACES

diff  --git a/mlir/lib/Dialect/SPIRV/CMakeLists.txt b/mlir/lib/Dialect/SPIRV/CMakeLists.txt
index 4d73d45f39ec0..211f67afd9fd0 100644
--- a/mlir/lib/Dialect/SPIRV/CMakeLists.txt
+++ b/mlir/lib/Dialect/SPIRV/CMakeLists.txt
@@ -1,4 +1,5 @@
 add_subdirectory(IR)
+add_subdirectory(Interfaces)
 add_subdirectory(Linking)
 add_subdirectory(Transforms)
 add_subdirectory(Utils)

diff  --git a/mlir/lib/Dialect/SPIRV/IR/CMakeLists.txt b/mlir/lib/Dialect/SPIRV/IR/CMakeLists.txt
index 235beb0b6a097..1a8f30dd39871 100644
--- a/mlir/lib/Dialect/SPIRV/IR/CMakeLists.txt
+++ b/mlir/lib/Dialect/SPIRV/IR/CMakeLists.txt
@@ -35,6 +35,7 @@ add_mlir_dialect_library(MLIRSPIRVDialect
   MLIRSPIRVCanonicalizationIncGen
   MLIRSPIRVEnumAvailabilityIncGen
   MLIRSPIRVEnumsIncGen
+  MLIRSPIRVImageInterfacesIncGen
   MLIRSPIRVOpsIncGen
 
   LINK_LIBS PUBLIC
@@ -43,6 +44,7 @@ add_mlir_dialect_library(MLIRSPIRVDialect
   MLIRIR
   MLIRParser
   MLIRSideEffectInterfaces
+  MLIRSPIRVImageInterfaces
   MLIRSupport
   MLIRTransforms
   MLIRUBDialect

diff  --git a/mlir/lib/Dialect/SPIRV/IR/ImageOps.cpp b/mlir/lib/Dialect/SPIRV/IR/ImageOps.cpp
index daf6d84660f2a..b198294b9bdd6 100644
--- a/mlir/lib/Dialect/SPIRV/IR/ImageOps.cpp
+++ b/mlir/lib/Dialect/SPIRV/IR/ImageOps.cpp
@@ -18,6 +18,8 @@ using namespace mlir;
 // Common utility functions
 //===----------------------------------------------------------------------===//
 
+// TODO: In the future we should model image operands better, so we can move
+// some verification into ODS.
 static LogicalResult verifyImageOperands(Operation *imageOp,
                                          spirv::ImageOperandsAttr attr,
                                          Operation::operand_range operands) {
@@ -29,10 +31,123 @@ static LogicalResult verifyImageOperands(Operation *imageOp,
                               "follow, as per Image Operands");
   }
 
+  if (spirv::bitEnumContainsAll(attr.getValue(),
+                                spirv::ImageOperands::Lod |
+                                    spirv::ImageOperands::Grad))
+    return imageOp->emitError(
+        "it is invalid to set both the Lod and Grad bits");
+
+  size_t index = 0;
+
+  // The order we process operands is important. In case of multiple argument
+  // taking operands, the arguments are ordered starting with operands having
+  // smaller-numbered bits first.
+  if (spirv::bitEnumContainsAny(attr.getValue(), spirv::ImageOperands::Lod)) {
+    if (!isa<spirv::ExplicitLodOpInterface>(imageOp) &&
+        !isa<spirv::FetchOpInterface>(imageOp))
+      return imageOp->emitError(
+          "Lod is only valid with explicit-lod and fetch instructions");
+
+    if (index + 1 > operands.size())
+      return imageOp->emitError("Lod operand requires 1 argument");
+
+    spirv::ImageType imageType;
+
+    if (isa<spirv::SamplingOpInterface>(imageOp)) {
+      if (!isa<mlir::FloatType>(operands[index].getType()))
+        return imageOp->emitError("for sampling operations, Lod must be a "
+                                  "floating-point type scalar");
+
+      auto samplingOp = cast<spirv::SamplingOpInterface>(imageOp);
+      auto sampledImageType = llvm::cast<spirv::SampledImageType>(
+          samplingOp.getSampledImage().getType());
+      imageType = cast<spirv::ImageType>(sampledImageType.getImageType());
+    } else {
+      if (!isa<mlir::IntegerType>(operands[index].getType()))
+        return imageOp->emitError(
+            "for fetch operations, Lod must be an integer type scalar");
+
+      auto fetchOp = cast<spirv::FetchOpInterface>(imageOp);
+      imageType = cast<spirv::ImageType>(fetchOp.getImage().getType());
+    }
+
+    if (!llvm::is_contained({spirv::Dim::Dim1D, spirv::Dim::Dim2D,
+                             spirv::Dim::Dim3D, spirv::Dim::Cube},
+                            imageType.getDim()))
+      return imageOp->emitError("Lod only be used with an image type that has "
+                                "a dim operand of 1D, 2D, 3D, or Cube");
+
+    if (imageType.getSamplingInfo() != spirv::ImageSamplingInfo::SingleSampled)
+      return imageOp->emitError(
+          "Lod only be used with an image type that has a MS operand of 0");
+
+    ++index;
+  }
+
+  if (spirv::bitEnumContainsAny(attr.getValue(), spirv::ImageOperands::Grad)) {
+    if (!isa<spirv::ExplicitLodOpInterface>(imageOp))
+      return imageOp->emitError(
+          "Grad is only valid with explicit-lod instructions");
+
+    if (index + 2 > operands.size())
+      return imageOp->emitError(
+          "Grad operand requires 2 arguments (scalars or vectors)");
+
+    auto samplingOp = cast<spirv::SamplingOpInterface>(imageOp);
+    auto sampledImageType =
+        cast<spirv::SampledImageType>(samplingOp.getSampledImage().getType());
+    auto imageType = cast<spirv::ImageType>(sampledImageType.getImageType());
+
+    if (imageType.getSamplingInfo() != spirv::ImageSamplingInfo::SingleSampled)
+      return imageOp->emitError(
+          "Grad only be used with an image type that has a MS operand of 0");
+
+    int64_t numberOfComponents = 0;
+
+    auto coordVector =
+        dyn_cast<mlir::VectorType>(samplingOp.getCoordinate().getType());
+    if (coordVector) {
+      numberOfComponents = coordVector.getNumElements();
+      if (imageType.getArrayedInfo() == spirv::ImageArrayedInfo::Arrayed)
+        numberOfComponents -= 1;
+    } else {
+      numberOfComponents = 1;
+    }
+
+    assert(numberOfComponents > 0);
+
+    auto dXVector = dyn_cast<mlir::VectorType>(operands[index].getType());
+    auto dYVector = dyn_cast<mlir::VectorType>(operands[index + 1].getType());
+    if (dXVector && dYVector) {
+      if (dXVector.getNumElements() != dYVector.getNumElements() ||
+          dXVector.getNumElements() != numberOfComponents)
+        return imageOp->emitError(
+            "number of components of each Grad argument must equal the number "
+            "of components in coordinate, minus the array layer component, if "
+            "present");
+
+      if (!isa<mlir::FloatType>(dXVector.getElementType()) ||
+          !isa<mlir::FloatType>(dYVector.getElementType()))
+        return imageOp->emitError(
+            "Grad arguments must be a vector of floating-point type");
+    } else if (isa<mlir::FloatType>(operands[index].getType()) &&
+               isa<mlir::FloatType>(operands[index + 1].getType())) {
+      if (numberOfComponents != 1)
+        return imageOp->emitError(
+            "number of components of each Grad argument must equal the number "
+            "of components in coordinate, minus the array layer component, if "
+            "present");
+    } else {
+      return imageOp->emitError(
+          "Grad arguments must be a scalar or vector of floating-point type");
+    }
+
+    index += 2;
+  }
+
   // TODO: Add the validation rules for the following Image Operands.
   spirv::ImageOperands noSupportOperands =
-      spirv::ImageOperands::Bias | spirv::ImageOperands::Lod |
-      spirv::ImageOperands::Grad | spirv::ImageOperands::ConstOffset |
+      spirv::ImageOperands::Bias | spirv::ImageOperands::ConstOffset |
       spirv::ImageOperands::Offset | spirv::ImageOperands::ConstOffsets |
       spirv::ImageOperands::Sample | spirv::ImageOperands::MinLod |
       spirv::ImageOperands::MakeTexelAvailable |
@@ -43,6 +158,10 @@ static LogicalResult verifyImageOperands(Operation *imageOp,
          "unimplemented operands of Image Operands");
   (void)noSupportOperands;
 
+  if (index < operands.size())
+    return imageOp->emitError(
+        "too many image operand arguments have been provided");
+
   return success();
 }
 
@@ -136,3 +255,33 @@ LogicalResult spirv::ImageQuerySizeOp::verify() {
 
   return success();
 }
+
+//===----------------------------------------------------------------------===//
+// spirv.ImageSampleImplicitLod
+//===----------------------------------------------------------------------===//
+
+LogicalResult spirv::ImageSampleImplicitLodOp::verify() {
+  return verifyImageOperands(getOperation(), getImageOperandsAttr(),
+                             getOperandArguments());
+}
+
+//===----------------------------------------------------------------------===//
+// spirv.ImageSampleExplicitLod
+//===----------------------------------------------------------------------===//
+
+LogicalResult spirv::ImageSampleExplicitLodOp::verify() {
+  // TODO: It should be verified somewhere that: "Unless the Kernel capability
+  // is declared, it [Coordinate] must be floating point."
+
+  return verifyImageOperands(getOperation(), getImageOperandsAttr(),
+                             getOperandArguments());
+}
+
+//===----------------------------------------------------------------------===//
+// spirv.ImageSampleProjDrefImplicitLod
+//===----------------------------------------------------------------------===//
+
+LogicalResult spirv::ImageSampleProjDrefImplicitLodOp::verify() {
+  return verifyImageOperands(getOperation(), getImageOperandsAttr(),
+                             getOperandArguments());
+}

diff  --git a/mlir/lib/Dialect/SPIRV/Interfaces/CMakeLists.txt b/mlir/lib/Dialect/SPIRV/Interfaces/CMakeLists.txt
new file mode 100644
index 0000000000000..2868e3b641b91
--- /dev/null
+++ b/mlir/lib/Dialect/SPIRV/Interfaces/CMakeLists.txt
@@ -0,0 +1,12 @@
+add_mlir_library(MLIRSPIRVImageInterfaces
+  SPIRVImageInterfaces.cpp
+
+  ADDITIONAL_HEADER_DIRS
+  ${MLIR_MAIN_INCLUDE_DIR}/mlir/Dialect/SPIRV
+
+  DEPENDS
+  MLIRSPIRVImageInterfacesIncGen
+
+  LINK_LIBS PUBLIC
+  MLIRIR
+)

diff  --git a/mlir/lib/Dialect/SPIRV/Interfaces/SPIRVImageInterfaces.cpp b/mlir/lib/Dialect/SPIRV/Interfaces/SPIRVImageInterfaces.cpp
new file mode 100644
index 0000000000000..e10da60184eeb
--- /dev/null
+++ b/mlir/lib/Dialect/SPIRV/Interfaces/SPIRVImageInterfaces.cpp
@@ -0,0 +1,13 @@
+//===- SPIRVImageInterfaces.cpp ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/SPIRV/IR/SPIRVOps.h"
+
+using namespace mlir;
+
+#include "mlir/Dialect/SPIRV/Interfaces/SPIRVImageInterfaces.cpp.inc"

diff  --git a/mlir/test/Dialect/SPIRV/IR/image-ops.mlir b/mlir/test/Dialect/SPIRV/IR/image-ops.mlir
index 0e8a6df5a1d7b..9a0b8b79e3e01 100644
--- a/mlir/test/Dialect/SPIRV/IR/image-ops.mlir
+++ b/mlir/test/Dialect/SPIRV/IR/image-ops.mlir
@@ -157,3 +157,221 @@ func.func @image_write_texel_type_mismatch(%arg0 : !spirv.image<f32, Dim2D, NoDe
   spirv.ImageWrite %arg0, %arg1, %arg2 : !spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NoSampler, Rgba16>, vector<2xsi32>, vector<4xi32>
   spirv.Return
 }
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spirv.ImageSampleExplicitLod
+//===----------------------------------------------------------------------===//
+
+func.func @sample_explicit_lod(%arg0 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, %arg1 : vector<2xf32>, %arg2 : f32) -> () {
+  // CHECK: {{%.*}} = spirv.ImageSampleExplicitLod {{%.*}}, {{%.*}} ["Lod"], {{%.*}} : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, vector<2xf32>, f32 -> vector<4xf32>
+  %0 = spirv.ImageSampleExplicitLod %arg0, %arg1 ["Lod"], %arg2 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, vector<2xf32>, f32 -> vector<4xf32>
+  spirv.Return
+}
+
+// -----
+
+func.func @sample_explicit_lod_buffer_dim(%arg0 : !spirv.sampled_image<!spirv.image<f32, Buffer, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, %arg1 : vector<2xf32>, %arg2 : f32) -> () {
+  // expected-error @+1 {{the Dim operand of the underlying image must not be Buffer}}
+  %0 = spirv.ImageSampleExplicitLod %arg0, %arg1 ["Lod"], %arg2 : !spirv.sampled_image<!spirv.image<f32, Buffer, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, vector<2xf32>, f32 -> vector<4xf32>
+  spirv.Return
+}
+
+// -----
+
+func.func @sample_explicit_lod_multi_sampled(%arg0 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, MultiSampled, NeedSampler, Rgba8>>, %arg1 : vector<2xf32>, %arg2 : f32) -> () {
+  // expected-error @+1 {{the MS operand of the underlying image type must be SingleSampled}}
+  %0 = spirv.ImageSampleExplicitLod %arg0, %arg1 ["Lod"], %arg2 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, MultiSampled, NeedSampler, Rgba8>>, vector<2xf32>, f32 -> vector<4xf32>
+  spirv.Return
+}
+
+// -----
+
+func.func @sample_explicit_lod_wrong_result_type(%arg0 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, %arg1 : vector<2xf32>, %arg2 : f32) -> () {
+  // expected-error @+1 {{the result component type must match the image sampled type}}
+  %0 = spirv.ImageSampleExplicitLod %arg0, %arg1 ["Lod"], %arg2 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, vector<2xf32>, f32 -> vector<4xsi32>
+  spirv.Return
+}
+
+// -----
+
+func.func @sample_explicit_lod_no_lod(%arg0 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, %arg1 : vector<2xf32>, %arg2 : f32) -> () {
+  // expected-error @+1 {{either Lod or Grad image operands must be present}}
+  %0 = spirv.ImageSampleExplicitLod %arg0, %arg1 ["Bias"], %arg2 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, vector<2xf32>, f32 -> vector<4xf32>
+  spirv.Return
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spirv.ImageSampleImplicitLod
+//===----------------------------------------------------------------------===//
+
+func.func @sample_implicit_lod(%arg0 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, %arg1 : vector<2xf32>) -> () {
+  // CHECK: {{%.*}} = spirv.ImageSampleImplicitLod {{%.*}}, {{%.*}} : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, vector<2xf32> -> vector<4xf32>
+  %0 = spirv.ImageSampleImplicitLod %arg0, %arg1 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, vector<2xf32> -> vector<4xf32>
+  spirv.Return
+}
+
+// -----
+
+func.func @sample_implicit_lod_buffer(%arg0 : !spirv.sampled_image<!spirv.image<f32, Buffer, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, %arg1 : vector<2xf32>) -> () {
+  // expected-error @+1 {{the Dim operand of the underlying image must not be Buffer}}
+  %0 = spirv.ImageSampleImplicitLod %arg0, %arg1 : !spirv.sampled_image<!spirv.image<f32, Buffer, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, vector<2xf32> -> vector<4xf32>
+  spirv.Return
+}
+
+// -----
+
+func.func @sample_implicit_lod_multi_sampled(%arg0 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, MultiSampled, NeedSampler, Rgba8>>, %arg1 : vector<2xf32>) -> () {
+  // expected-error @+1 {{the MS operand of the underlying image type must be SingleSampled}}
+  %0 = spirv.ImageSampleImplicitLod %arg0, %arg1 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, MultiSampled, NeedSampler, Rgba8>>, vector<2xf32> -> vector<4xf32>
+  spirv.Return
+}
+
+// -----
+
+func.func @sample_implicit_lod_wrong_result(%arg0 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, %arg1 : vector<2xf32>) -> () {
+  // expected-error @+1 {{the result component type must match the image sampled type}}
+  %0 = spirv.ImageSampleImplicitLod %arg0, %arg1 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, vector<2xf32> -> vector<4xi32>
+  spirv.Return
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spirv.ImageSampleProjDrefImplicitLod
+//===----------------------------------------------------------------------===//
+
+func.func @sample_implicit_proj_dref(%arg0 : !spirv.sampled_image<!spirv.image<f32, Dim2D, IsDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, %arg1 : vector<4xf32>, %arg2 : f32) -> () {
+  // CHECK: {{%.*}} = spirv.ImageSampleProjDrefImplicitLod {{%.*}}, {{%.*}}, {{%.*}} : !spirv.sampled_image<!spirv.image<f32, Dim2D, IsDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, vector<4xf32>, f32 -> f32
+  %0 = spirv.ImageSampleProjDrefImplicitLod %arg0, %arg1, %arg2 : !spirv.sampled_image<!spirv.image<f32, Dim2D, IsDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, vector<4xf32>, f32 -> f32
+  spirv.Return
+}
+
+// -----
+
+func.func @sample_implicit_proj_dref_buffer_dim(%arg0 : !spirv.sampled_image<!spirv.image<f32, Buffer, IsDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, %arg1 : vector<4xf32>, %arg2 : f32) -> () {
+  // expected-error @+1 {{the Dim operand of the underlying image must not be Buffer}}
+  %0 = spirv.ImageSampleProjDrefImplicitLod %arg0, %arg1, %arg2 : !spirv.sampled_image<!spirv.image<f32, Buffer, IsDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, vector<4xf32>, f32 -> f32
+  spirv.Return
+}
+
+// -----
+
+func.func @sample_implicit_proj_dref_multi_sampled(%arg0 : !spirv.sampled_image<!spirv.image<f32, Dim2D, IsDepth, NonArrayed, MultiSampled, NeedSampler, Rgba8>>, %arg1 : vector<4xf32>, %arg2 : f32) -> () {
+  // expected-error @+1 {{the MS operand of the underlying image type must be SingleSampled}}
+  %0 = spirv.ImageSampleProjDrefImplicitLod %arg0, %arg1, %arg2 : !spirv.sampled_image<!spirv.image<f32, Dim2D, IsDepth, NonArrayed, MultiSampled, NeedSampler, Rgba8>>, vector<4xf32>, f32 -> f32
+  spirv.Return
+}
+
+// -----
+
+func.func @sample_implicit_proj_dref(%arg0 : !spirv.sampled_image<!spirv.image<f32, Dim2D, IsDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, %arg1 : vector<4xf32>, %arg2 : f32) -> () {
+  // expected-error @+1 {{type of 'result' matches image type of 'sampled_image'}}
+  %0 = spirv.ImageSampleProjDrefImplicitLod %arg0, %arg1, %arg2 : !spirv.sampled_image<!spirv.image<f32, Dim2D, IsDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, vector<4xf32>, f32 -> i32
+  spirv.Return
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spirv.ImageOperands: Lod
+//===----------------------------------------------------------------------===//
+
+func.func @grad_and_lod_set(%arg0 : !spirv.sampled_image<!spirv.image<f32, Dim1D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, %arg1 : f32, %arg2 : f32) -> () {
+  // expected-error @+1 {{it is invalid to set both the Lod and Grad bits}}
+  %0 = spirv.ImageSampleExplicitLod %arg0, %arg1 ["Lod | Grad"], %arg2, %arg2, %arg2 : !spirv.sampled_image<!spirv.image<f32, Dim1D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, f32, f32, f32, f32 -> vector<4xf32>
+  spirv.Return
+}
+
+// -----
+
+func.func @lod_with_implict_sample(%arg0 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, %arg1 : vector<2xf32>, %arg2 : f32) -> () {
+  // expected-error @+1 {{Lod is only valid with explicit-lod and fetch instructions}}
+  %0 = spirv.ImageSampleImplicitLod %arg0, %arg1 ["Lod"], %arg2 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, vector<2xf32>, f32 -> vector<4xf32>
+  spirv.Return
+}
+
+// -----
+
+func.func @lod_too_many_arguments(%arg0 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, %arg1 : vector<2xf32>, %arg2 : f32) -> () {
+  // expected-error @+1 {{too many image operand arguments have been provided}}
+  %0 = spirv.ImageSampleExplicitLod %arg0, %arg1 ["Lod"], %arg2, %arg2 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, vector<2xf32>, f32, f32 -> vector<4xf32>
+  spirv.Return
+}
+
+// -----
+
+func.func @lod_with_rect(%arg0 : !spirv.sampled_image<!spirv.image<f32, Rect, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, %arg1 : vector<2xf32>, %arg2 : f32) -> () {
+  // expected-error @+1 {{Lod only be used with an image type that has a dim operand of 1D, 2D, 3D, or Cube}}
+  %0 = spirv.ImageSampleExplicitLod %arg0, %arg1 ["Lod"], %arg2 : !spirv.sampled_image<!spirv.image<f32, Rect, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, vector<2xf32>, f32 -> vector<4xf32>
+  spirv.Return
+}
+
+// TODO: We cannot currently test Lod with MS != 0 as all implemented explicit operations already check for that.
+
+// TODO: Add Lod tests for fetch operations once available.
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spirv.ImageOperands: Grad
+//===----------------------------------------------------------------------===//
+
+func.func @gard_with_implicit_sample(%arg0 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, %arg1 : vector<2xf32>, %arg2 : vector<2xf32>) -> () {
+  // expected-error @+1 {{Grad is only valid with explicit-lod instructions}}
+  %0 = spirv.ImageSampleImplicitLod %arg0, %arg1 ["Grad"], %arg2, %arg2 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, vector<2xf32>, vector<2xf32>, vector<2xf32> -> vector<4xf32>
+  spirv.Return
+}
+
+// -----
+
+func.func @gard_not_enough_args(%arg0 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, %arg1 : vector<2xf32>, %arg2 : vector<2xf32>) -> () {
+  // expected-error @+1 {{Grad operand requires 2 arguments (scalars or vectors)}}
+  %0 = spirv.ImageSampleExplicitLod %arg0, %arg1 ["Grad"], %arg2 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, vector<2xf32>, vector<2xf32> -> vector<4xf32>
+  spirv.Return
+}
+
+// TODO: We cannot currently test Grad with MS != 0 as all implemented explicit operations already check for that.
+
+// -----
+
+func.func @grad_arg_size_mismatch(%arg0 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, %arg1 : vector<2xf32>, %arg2 : vector<3xf32>) -> () {
+  // expected-error @+1 {{number of components of each Grad argument must equal the number of components in coordinate, minus the array layer component, if present}}
+  %0 = spirv.ImageSampleExplicitLod %arg0, %arg1 ["Grad"], %arg2, %arg2 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, vector<2xf32>, vector<3xf32>, vector<3xf32> -> vector<4xf32>
+  spirv.Return
+}
+
+// -----
+
+func.func @gard_arg_wrong_type(%arg0 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, %arg1 : vector<2xf32>, %arg2 : vector<2xsi32>) -> () {
+  // expected-error @+1 {{Grad arguments must be a vector of floating-point type}}
+  %0 = spirv.ImageSampleExplicitLod %arg0, %arg1 ["Grad"], %arg2, %arg2 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, vector<2xf32>, vector<2xsi32>, vector<2xsi32> -> vector<4xf32>
+  spirv.Return
+}
+
+// -----
+
+func.func @gard_arg_size_mismatch_scalar(%arg0 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, %arg1 : vector<2xf32>, %arg2 : f32) -> () {
+  // expected-error @+1 {{number of components of each Grad argument must equal the number of components in coordinate, minus the array layer component, if present}}
+  %0 = spirv.ImageSampleExplicitLod %arg0, %arg1 ["Grad"], %arg2, %arg2 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, vector<2xf32>, f32, f32 -> vector<4xf32>
+  spirv.Return
+}
+
+// -----
+
+func.func @gard_int_args(%arg0 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, %arg1 : vector<2xf32>, %arg2 : i32) -> () {
+  // expected-error @+1 {{Grad arguments must be a scalar or vector of floating-point type}}
+  %0 = spirv.ImageSampleExplicitLod %arg0, %arg1 ["Grad"], %arg2, %arg2 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, vector<2xf32>, i32, i32 -> vector<4xf32>
+  spirv.Return
+}
+
+// -----
+
+func.func @gard_too_many_args(%arg0 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, %arg1 : vector<2xf32>, %arg2 : vector<2xf32>) -> () {
+  // expected-error @+1 {{too many image operand arguments have been provided}}
+  %0 = spirv.ImageSampleExplicitLod %arg0, %arg1 ["Grad"], %arg2, %arg2, %arg2 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, vector<2xf32>, vector<2xf32>, vector<2xf32>, vector<2xf32> -> vector<4xf32>
+  spirv.Return
+}

diff  --git a/mlir/test/Target/SPIRV/image-ops.mlir b/mlir/test/Target/SPIRV/image-ops.mlir
index 3c28c3f71bc2a..6dd23844d46a9 100644
--- a/mlir/test/Target/SPIRV/image-ops.mlir
+++ b/mlir/test/Target/SPIRV/image-ops.mlir
@@ -18,6 +18,21 @@ spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader, ImageQuery, Link
     spirv.ImageWrite %arg0, %arg1, %arg2 : !spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NoSampler, Rgba8>, vector<2xsi32>, vector<4xf32>
     spirv.Return
   }
+  spirv.func @explicit_sample(%arg0 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, %arg1 : vector<2xf32>, %arg2 : f32) "None" {
+    // CHECK: {{%.*}} = spirv.ImageSampleExplicitLod {{%.*}}, {{%.*}} ["Lod"], {{%.*}} : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, vector<2xf32>, f32 -> vector<4xf32>
+    %0 = spirv.ImageSampleExplicitLod %arg0, %arg1 ["Lod"], %arg2 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, vector<2xf32>, f32 -> vector<4xf32>
+    spirv.Return
+  }
+  spirv.func @implicit_sample(%arg0 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, %arg1 : vector<3xf32>) "None" {
+    // CHECK: {{%.*}} = spirv.ImageSampleImplicitLod {{%.*}}, {{%.*}} : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, vector<3xf32> -> vector<4xf32>
+    %0 = spirv.ImageSampleImplicitLod %arg0, %arg1 : !spirv.sampled_image<!spirv.image<f32, Dim2D, NoDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, vector<3xf32> -> vector<4xf32>
+    spirv.Return
+  }
+  spirv.func @implicit_sample_proj_dref(%arg0 : !spirv.sampled_image<!spirv.image<f32, Dim2D, IsDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, %arg1 : vector<4xf32>, %arg2 : f32) "None" {
+    // CHECK: {{%.*}} = spirv.ImageSampleProjDrefImplicitLod {{%.*}}, {{%.*}}, {{%.*}} : !spirv.sampled_image<!spirv.image<f32, Dim2D, IsDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, vector<4xf32>, f32 -> f32
+    %0 = spirv.ImageSampleProjDrefImplicitLod %arg0, %arg1, %arg2 : !spirv.sampled_image<!spirv.image<f32, Dim2D, IsDepth, NonArrayed, SingleSampled, NeedSampler, Rgba8>>, vector<4xf32>, f32 -> f32
+    spirv.Return
+  }
 }
 
 // -----


        


More information about the Mlir-commits mailing list