Quellcode durchsuchen

Implement SPV_KHR_ray_query generation (#2834)

* Implement SPV_KHR_ray_query generation

from dxr 1.1 rayquery hlsl

* Fix CodeGenSPIRV folder test failures

* Address reviewing issues and clang-format files

* Undo all spacing changes to HlslTypes.cpp

* Fix formatting issues in the doc file.

Co-authored-by: Ehsan Nasiri <[email protected]>
JiaoluAMD vor 5 Jahren
Ursprung
Commit
fc54789458
31 geänderte Dateien mit 1388 neuen und 21 gelöschten Zeilen
  1. 176 2
      docs/SPIR-V.rst
  2. 2 1
      tools/clang/include/clang/SPIRV/FeatureManager.h
  3. 6 0
      tools/clang/include/clang/SPIRV/SpirvBuilder.h
  4. 5 0
      tools/clang/include/clang/SPIRV/SpirvContext.h
  5. 36 15
      tools/clang/include/clang/SPIRV/SpirvInstruction.h
  6. 11 0
      tools/clang/include/clang/SPIRV/SpirvType.h
  7. 1 1
      tools/clang/include/clang/SPIRV/SpirvVisitor.h
  8. 5 1
      tools/clang/lib/SPIRV/AstTypeProbe.cpp
  9. 16 0
      tools/clang/lib/SPIRV/CapabilityVisitor.cpp
  10. 21 0
      tools/clang/lib/SPIRV/EmitVisitor.cpp
  11. 1 0
      tools/clang/lib/SPIRV/EmitVisitor.h
  12. 3 0
      tools/clang/lib/SPIRV/FeatureManager.cpp
  13. 3 0
      tools/clang/lib/SPIRV/LowerTypeVisitor.cpp
  14. 11 0
      tools/clang/lib/SPIRV/SpirvBuilder.cpp
  15. 1 0
      tools/clang/lib/SPIRV/SpirvContext.cpp
  16. 361 1
      tools/clang/lib/SPIRV/SpirvEmitter.cpp
  17. 7 0
      tools/clang/lib/SPIRV/SpirvEmitter.h
  18. 7 0
      tools/clang/lib/SPIRV/SpirvInstruction.cpp
  19. 9 0
      tools/clang/test/CodeGenSPIRV/rayquery_assign.cs.hlsl
  20. 63 0
      tools/clang/test/CodeGenSPIRV/rayquery_init_ds.hlsl
  21. 43 0
      tools/clang/test/CodeGenSPIRV/rayquery_init_gs.hlsl
  22. 75 0
      tools/clang/test/CodeGenSPIRV/rayquery_init_hs.hlsl
  23. 33 0
      tools/clang/test/CodeGenSPIRV/rayquery_init_ps.hlsl
  24. 42 0
      tools/clang/test/CodeGenSPIRV/rayquery_init_rahit.hlsl
  25. 37 0
      tools/clang/test/CodeGenSPIRV/rayquery_init_rcall.hlsl
  26. 42 0
      tools/clang/test/CodeGenSPIRV/rayquery_init_rchit.hlsl
  27. 42 0
      tools/clang/test/CodeGenSPIRV/rayquery_init_rgen.hlsl
  28. 41 0
      tools/clang/test/CodeGenSPIRV/rayquery_init_rint.hlsl
  29. 37 0
      tools/clang/test/CodeGenSPIRV/rayquery_init_rmiss.hlsl
  30. 45 0
      tools/clang/test/CodeGenSPIRV/rayquery_init_vs.hlsl
  31. 206 0
      tools/clang/test/CodeGenSPIRV/rayquery_tryAllOps.cs.hlsl

+ 176 - 2
docs/SPIR-V.rst

@@ -3086,7 +3086,7 @@ Miss Stage
 Callable Stage
 ~~~~~~~~~~~~~~
 
-| Callables are generic function calls which can be invoked from either raygeneration, closest-hit, 
+| Callables are generic function calls which can be invoked from either raygeneration, closest-hit,
 | miss or callable shader stages.
 | Entry functions of this stage are annotated with **[shader("callable")]** in HLSL source.
 | Such entry functions must return void and accept exactly one argument. First argument must be an inout
@@ -3173,7 +3173,7 @@ Mesh Interface Variables
 +-----------------+-------------------------------------------------------------------------+
 |  HLSL modifier  | SPIR-V definition                                                       |
 +=================+=========================================================================+
-| ``indices``     | Maps to SPIR-V intrinsic ``PrimitiveIndicesNV``                         |  
+| ``indices``     | Maps to SPIR-V intrinsic ``PrimitiveIndicesNV``                         |
 |                 |                                                                         |
 |                 | Defines SPIR-V Execution Mode ``OutputPrimitivesNV <array-size>``       |
 +-----------------+-------------------------------------------------------------------------+
@@ -3282,6 +3282,180 @@ Interface Variables
 ``IncomingCallableData{NV/KHR}``        First argument of entry for Callable stage
 =================================       ===========================================================
 
+RayQuery
+--------
+
+Ray Query is subfeature of the DirectX ray tracing and belongs to the DirectX ray tracing spec 1.1 (DXR 1.1).
+DirectX add RayQuery object type and its member TraceRayInline() to do the TraceRay() that doesn't
+use any seperate ray-tracing shader stages.
+Shaders can instantiate RayQuery objects as local variables, the RayQuery object acts as a state
+machine for ray query. The shader interacts with the RayQuery object's methods to advance the
+query through an acceleration structure and query traversal information
+
+Refer to following pages for details:
+https://microsoft.github.io/DirectX-Specs/d3d/Raytracing.html
+
+A flow chart for a simple ray query process
+
+::
+
+          +------------------------------+
+          |   RayQuery<RAY_FLAG_NONE> q  |
+          +------------------------------+
+                         |
+                         V
+          +------------------------------+
+          |      q.TraceRayInline()      |
+          +------------------------------+
+                  |               — — — — — — — — — — — — —
+                  |              |                         |
+                  |              |              +------------------------+
+                  |              |              | Your intersection code |
+                  |              |              +------------------------+
+                  |              |                         ^
+                  V              V                         |
+          +------------------------------+      +---------------------+
+          |  q.Proceed() // AS traversal |      |  q.CandidateType()  |
+          +------------------------------+      +---------------------+
+               |                   |                       ^
+           No  |                   | Yes                   |
+               |                   |_ _ _ _ _ _ _ _ _ _ _ _|
+               V
+         +------------------------------+
+         |     q.CommittedStatus()      |
+         +------------------------------+
+                       |
+                       V
+        +----------------------------------+
+        | Your Intersection/shader code    |
+        +----------------------------------+
+
+
+Example:
+
+.. code:: hlsl
+
+  void main() {
+    RayQuery<RAY_FLAG_CULL_NON_OPAQUE | RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH> q;
+    q.TraceRayInline(myAccelerationStructure, 0 , 0xff, myRay);
+  
+    // Proceed() is AccelerationStructure traversal loop take places
+    while(q.Proceed()) {
+      switch(q.CandidateType()) {
+        // retrieve intersection information/Do the shadering
+      }
+    }
+  
+    // AccelerationStructure traversal end
+    // Get the Committed status
+    switch(q.CommittedStatus()) {
+      // retrieve intersection information/ Do the shadering
+    }
+  }
+
+Ray Query in SPIRV
+~~~~~~~~~~~~~~~~~~
+RayQuery SPIR-V codegen is currently supported via SPV_KHR_ray_query extension
+SPIR-V specification for reference:
+https://github.com/KhronosGroup/SPIRV-Registry/blob/master/extensions/KHR/SPV_KHR_ray_query.asciidoc
+
+Object Type
+~~~~~~~~~~~
+RayQuery<RAY_FLAGS>
+
+RayQuery represents the state of an inline ray tracing call into an acceleration structure.
+
+
+============ ================================
+ HLSL Type            SPIR-V Opcode
+------------ --------------------------------
+``RayQuery`` ``OpTypeRayQueryProvisionalKHR``
+============ ================================
+
+RayQuery Mapping to SPIR-V
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
++---------------------------------------------------+-------------------------------------------------------------------------+
+|      HLSL  RayQuery member Intrinsic              |             SPIR-V Opcode                                               |
++===================================================+=========================================================================+
+|``.Abort``                                         | ``OpRayQueryTerminateKHR``                                              |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CandidateType``                                 | ``OpRayQueryGetIntersectionTypeKHR``                                    |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CandidateProceduralPrimitiveNonOpaque``         | ``OpRayQueryGetIntersectionCandidateAABBOpaqueKHR``                     |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CandidateInstanceIndex``                        | ``OpRayQueryGetIntersectionInstanceIdKHR``                              |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CandidateInstanceID``                           | ``OpRayQueryGetIntersectionInstanceCustomIndexKHR``                     |
++---------------------------------------------------+-------------------------------------------------------------------------+
+| ``.CandidateInstanceContributionToHitGroupIndex`` | ``OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR``  |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CandidateGeometryIndex``                        | ``OpRayQueryGetIntersectionGeometryIndexKHR``                           |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CandidatePrimitiveIndex``                       | ``OpRayQueryGetIntersectionPrimitiveIndexKHR``                          |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CandidateObjectRayOrigin``                      | ``OpRayQueryGetIntersectionObjectRayOriginKHR``                         |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CandidateObjectRayDirection``                   | ``OpRayQueryGetIntersectionObjectRayDirectionKHR``                      |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CandidateObjectToWorld3x4``                     | ``OpRayQueryGetIntersectionObjectToWorldKHR``                           |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CandidateObjectToWorld4x3``                     | ``OpRayQueryGetIntersectionObjectToWorldKHR``                           |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CandidateWorldToObject3x4``                     | ``OpRayQueryGetIntersectionWorldToObjectKHR``                           |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CandidateWorldToObject4x3``                     | ``OpRayQueryGetIntersectionWorldToObjectKHR``                           |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CandidateTriangleBarycentrics``                 | ``OpRayQueryGetIntersectionBarycentricsKHR``                            |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CandidateTriangleFrontFace``                    | ``OpRayQueryGetIntersectionFrontFaceKHR``                               |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CommittedStatus``                               | ``OpRayQueryGetIntersectionTypeKHR``                                    |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CommittedInstanceIndex``                        | ``OpRayQueryGetIntersectionInstanceIdKHR``                              |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CommittedInstanceID``                           | ``OpRayQueryGetIntersectionInstanceCustomIndexKHR``                     |
++---------------------------------------------------+-------------------------------------------------------------------------+
+| ``.CommittedInstanceContributionToHitGroupIndex`` |  ``OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR`` |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CommittedGeometryIndex``                        | ``OpRayQueryGetIntersectionGeometryIndexKHR``                           |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CommittedPrimitiveIndex``                       | ``OpRayQueryGetIntersectionPrimitiveIndexKHR``                          |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CommittedRayT``                                 | ``OpRayQueryGetIntersectionTKHR``                                       |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CommittedObjectRayOrigin``                      | ``OpRayQueryGetIntersectionObjectRayOriginKHR``                         |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CommittedObjectRayDirection``                   | ``OpRayQueryGetIntersectionObjectRayDirectionKHR``                      |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CommittedObjectToWorld3x4``                     | ``OpRayQueryGetIntersectionObjectToWorldKHR``                           |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CommittedObjectToWorld4x3``                     | ``OpRayQueryGetIntersectionObjectToWorldKHR``                           |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CommittedWorldToObject3x4``                     | ``OpRayQueryGetIntersectionWorldToObjectKHR``                           |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CommittedWorldToObject4x3``                     | ``OpRayQueryGetIntersectionWorldToObjectKHR``                           |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CommittedTriangleBarycentrics``                 | ``OpRayQueryGetIntersectionBarycentricsKHR``                            |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CommittedTriangleFrontFace``                    | ``OpRayQueryGetIntersectionFrontFaceKHR``                               |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CommitNonOpaqueTriangleHit``                    | ``OpRayQueryConfirmIntersectionKHR``                                    |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.CommitProceduralPrimitiveHit``                  | ``OpRayQueryGenerateIntersectionKHR``                                   |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.Proceed``                                       | ``OpRayQueryProceedKHR``                                                |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.RayFlags``                                      | ``OpRayQueryGetRayFlagsKHR``                                            |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.RayTMin``                                       | ``OpRayQueryGetRayTMinKHR``                                             |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.TraceRayInline``                                | ``OpRayQueryInitializeKHR``                                             |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.WorldRayDirection``                             | ``OpRayQueryGetWorldRayDirectionKHR``                                   |
++---------------------------------------------------+-------------------------------------------------------------------------+
+|``.WorldRayOrigin`                                 | ``OpRayQueryGetWorldRayOriginKHR``                                      |
++---------------------------------------------------+-------------------------------------------------------------------------+
 
 Shader Model 6.0 Wave Intrinsics
 ================================

+ 2 - 1
tools/clang/include/clang/SPIRV/FeatureManager.h

@@ -17,9 +17,9 @@
 
 #include "spirv-tools/libspirv.h"
 
+#include "dxc/Support/SPIRVOptions.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/SourceLocation.h"
-#include "dxc/Support/SPIRVOptions.h"
 #include "llvm/ADT/SmallBitVector.h"
 #include "llvm/ADT/StringRef.h"
 
@@ -48,6 +48,7 @@ enum class Extension {
   GOOGLE_user_type,
   NV_ray_tracing,
   NV_mesh_shader,
+  KHR_ray_query,
   Unknown,
 };
 

+ 6 - 0
tools/clang/include/clang/SPIRV/SpirvBuilder.h

@@ -437,6 +437,12 @@ public:
   /// \brief Creates an OpDemoteToHelperInvocationEXT instruction.
   SpirvInstruction *createDemoteToHelperInvocationEXT(SourceLocation);
 
+  /// \brief Create SPIR-V instructions for KHR RayQuery ops
+  SpirvInstruction *
+  createRayQueryOpsKHR(spv::Op opcode, QualType resultType,
+                       llvm::ArrayRef<SpirvInstruction *> operands,
+                       bool cullFlags, SourceLocation loc);
+
   // === SPIR-V Module Structure ===
   inline void setMemoryModel(spv::AddressingModel, spv::MemoryModel);
 

+ 5 - 0
tools/clang/include/clang/SPIRV/SpirvContext.h

@@ -185,6 +185,10 @@ public:
     return accelerationStructureTypeNV;
   }
 
+  const RayQueryProvisionalTypeKHR *getRayQueryProvisionalTypeKHR() const {
+    return rayQueryProvisionalTypeKHR;
+  }
+
   /// --- Hybrid type getter functions ---
   ///
   /// Concrete SpirvType objects represent a SPIR-V type completely. Hybrid
@@ -276,6 +280,7 @@ private:
   llvm::DenseMap<const SpirvType *, SCToPtrTyMap> pointerTypes;
   llvm::DenseSet<FunctionType *, FunctionTypeMapInfo> functionTypes;
   const AccelerationStructureTypeNV *accelerationStructureTypeNV;
+  const RayQueryProvisionalTypeKHR *rayQueryProvisionalTypeKHR;
 
   // Current ShaderModelKind for entry point.
   ShaderModelKind curShaderModelKind;

+ 36 - 15
tools/clang/include/clang/SPIRV/SpirvInstruction.h

@@ -103,22 +103,22 @@ public:
     IK_GroupNonUniformElect,    // OpGroupNonUniformElect
     IK_GroupNonUniformUnaryOp,  // Group non-uniform unary operations
 
-    IK_ImageOp,                   // OpImage*
-    IK_ImageQuery,                // OpImageQuery*
-    IK_ImageSparseTexelsResident, // OpImageSparseTexelsResident
-    IK_ImageTexelPointer,         // OpImageTexelPointer
-    IK_Load,                      // OpLoad
-    IK_SampledImage,              // OpSampledImage
-    IK_Select,                    // OpSelect
-    IK_SpecConstantBinaryOp,      // SpecConstant binary operations
-    IK_SpecConstantUnaryOp,       // SpecConstant unary operations
-    IK_Store,                     // OpStore
-    IK_UnaryOp,                   // Unary operations
-    IK_VectorShuffle,             // OpVectorShuffle
-    IK_ArrayLength,               // OpArrayLength
-    IK_RayTracingOpNV,            // NV raytracing ops
-
+    IK_ImageOp,                     // OpImage*
+    IK_ImageQuery,                  // OpImageQuery*
+    IK_ImageSparseTexelsResident,   // OpImageSparseTexelsResident
+    IK_ImageTexelPointer,           // OpImageTexelPointer
+    IK_Load,                        // OpLoad
+    IK_SampledImage,                // OpSampledImage
+    IK_Select,                      // OpSelect
+    IK_SpecConstantBinaryOp,        // SpecConstant binary operations
+    IK_SpecConstantUnaryOp,         // SpecConstant unary operations
+    IK_Store,                       // OpStore
+    IK_UnaryOp,                     // Unary operations
+    IK_VectorShuffle,               // OpVectorShuffle
+    IK_ArrayLength,                 // OpArrayLength
+    IK_RayTracingOpNV,              // NV raytracing ops
     IK_DemoteToHelperInvocationEXT, // OpDemoteToHelperInvocationEXT
+    IK_RayQueryOpKHR,               // KHR rayquery ops
   };
 
   virtual ~SpirvInstruction() = default;
@@ -1750,6 +1750,27 @@ public:
 private:
   llvm::SmallVector<SpirvInstruction *, 4> operands;
 };
+class SpirvRayQueryOpKHR : public SpirvInstruction {
+public:
+  SpirvRayQueryOpKHR(QualType resultType, spv::Op opcode,
+                     llvm::ArrayRef<SpirvInstruction *> vecOperands, bool flags,
+                     SourceLocation loc);
+
+  // For LLVM-style RTTI
+  static bool classof(const SpirvInstruction *inst) {
+    return inst->getKind() == IK_RayQueryOpKHR;
+  }
+
+  bool invokeVisitor(Visitor *v) override;
+
+  llvm::ArrayRef<SpirvInstruction *> getOperands() const { return operands; }
+
+  bool hasCullFlags() const { return cullFlags; }
+
+private:
+  llvm::SmallVector<SpirvInstruction *, 4> operands;
+  bool cullFlags;
+};
 
 /// \brief OpDemoteToHelperInvocationEXT instruction.
 /// Demote fragment shader invocation to a helper invocation. Any stores to

+ 11 - 0
tools/clang/include/clang/SPIRV/SpirvType.h

@@ -48,6 +48,7 @@ public:
     TK_Pointer,
     TK_Function,
     TK_AccelerationStructureNV,
+    TK_RayQueryProvisionalKHR,
     // Order matters: all the following are hybrid types
     TK_HybridStruct,
     TK_HybridPointer,
@@ -399,6 +400,16 @@ public:
   }
 };
 
+class RayQueryProvisionalTypeKHR : public SpirvType {
+public:
+  RayQueryProvisionalTypeKHR()
+      : SpirvType(TK_RayQueryProvisionalKHR, "rayQueryProvisionalKHR") {}
+
+  static bool classof(const SpirvType *t) {
+    return t->getKind() == TK_RayQueryProvisionalKHR;
+  }
+};
+
 class HybridType : public SpirvType {
 public:
   static bool classof(const SpirvType *t) {

+ 1 - 1
tools/clang/include/clang/SPIRV/SpirvVisitor.h

@@ -114,7 +114,7 @@ public:
   DEFINE_VISIT_METHOD(SpirvArrayLength)
   DEFINE_VISIT_METHOD(SpirvRayTracingOpNV)
   DEFINE_VISIT_METHOD(SpirvDemoteToHelperInvocationEXT)
-
+  DEFINE_VISIT_METHOD(SpirvRayQueryOpKHR)
 #undef DEFINE_VISIT_METHOD
 
 protected:

+ 5 - 1
tools/clang/lib/SPIRV/AstTypeProbe.cpp

@@ -908,6 +908,9 @@ bool isOpaqueType(QualType type) {
 
     if (name == "RaytracingAccelerationStructure")
       return true;
+
+    if (name == "RayQuery")
+      return true;
   }
   return false;
 }
@@ -1097,7 +1100,8 @@ bool isOrContainsNonFpColMajorMatrix(const ASTContext &astContext,
     if (isMxNMatrix(arrayType->getElementType(), &elemType) &&
         !elemType->isFloatingType())
       return isColMajorDecl(decl);
-    if (const auto *structType = arrayType->getElementType()->getAs<RecordType>()) {
+    if (const auto *structType =
+            arrayType->getElementType()->getAs<RecordType>()) {
       return isOrContainsNonFpColMajorMatrix(astContext, spirvOptions,
                                              arrayType->getElementType(),
                                              structType->getDecl());

+ 16 - 0
tools/clang/lib/SPIRV/CapabilityVisitor.cpp

@@ -195,6 +195,12 @@ void CapabilityVisitor::addCapabilityForType(const SpirvType *type,
     for (auto field : structType->getFields())
       addCapabilityForType(field.type, loc, sc);
   }
+  //
+  else if (const auto *rayQueryType =
+               dyn_cast<RayQueryProvisionalTypeKHR>(type)) {
+    addCapability(spv::Capability::RayQueryProvisionalKHR);
+    addExtension(Extension::KHR_ray_query, "SPV_KHR_ray_query", {});
+  }
 }
 
 bool CapabilityVisitor::visit(SpirvDecoration *decor) {
@@ -475,6 +481,16 @@ bool CapabilityVisitor::visitInstruction(SpirvInstruction *instr) {
     }
     break;
   }
+  case spv::Op::OpRayQueryInitializeKHR: {
+    auto rayQueryInst = dyn_cast<SpirvRayQueryOpKHR>(instr);
+    if (rayQueryInst->hasCullFlags()) {
+      addCapability(
+          spv::Capability::RayTraversalPrimitiveCullingProvisionalKHR);
+    }
+
+    break;
+  }
+
   default:
     break;
   }

+ 21 - 0
tools/clang/lib/SPIRV/EmitVisitor.cpp

@@ -1126,6 +1126,20 @@ bool EmitVisitor::visit(SpirvDemoteToHelperInvocationEXT *inst) {
   return true;
 }
 
+bool EmitVisitor::visit(SpirvRayQueryOpKHR *inst) {
+  initInstruction(inst);
+  if (inst->hasResultType()) {
+    curInst.push_back(inst->getResultTypeId());
+    curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
+  }
+  for (const auto operand : inst->getOperands())
+    curInst.push_back(getOrAssignResultId<SpirvInstruction>(operand));
+  finalizeInstruction();
+  emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
+                              inst->getDebugName());
+  return true;
+}
+
 // EmitTypeHandler ------
 
 void EmitTypeHandler::initTypeInstruction(spv::Op op) {
@@ -1643,6 +1657,13 @@ uint32_t EmitTypeHandler::emitType(const SpirvType *type) {
     curTypeInst.push_back(id);
     finalizeTypeInstruction();
   }
+  // RayQueryProvisionalType KHR type
+  else if (const auto *rayQueryType =
+               dyn_cast<RayQueryProvisionalTypeKHR>(type)) {
+    initTypeInstruction(spv::Op::OpTypeRayQueryProvisionalKHR);
+    curTypeInst.push_back(id);
+    finalizeTypeInstruction();
+  }
   // Hybrid Types
   // Note: The type lowering pass should lower all types to SpirvTypes.
   // Therefore, if we find a hybrid type when going through the emitting pass,

+ 1 - 0
tools/clang/lib/SPIRV/EmitVisitor.h

@@ -259,6 +259,7 @@ public:
   bool visit(SpirvArrayLength *);
   bool visit(SpirvRayTracingOpNV *);
   bool visit(SpirvDemoteToHelperInvocationEXT *);
+  bool visit(SpirvRayQueryOpKHR *);
 
   // Returns the assembled binary built up in this visitor.
   std::vector<uint32_t> takeBinary();

+ 3 - 0
tools/clang/lib/SPIRV/FeatureManager.cpp

@@ -129,6 +129,7 @@ Extension FeatureManager::getExtensionSymbol(llvm::StringRef name) {
       .Case("SPV_KHR_post_depth_coverage", Extension::KHR_post_depth_coverage)
       .Case("SPV_NV_ray_tracing", Extension::NV_ray_tracing)
       .Case("SPV_NV_mesh_shader", Extension::NV_mesh_shader)
+      .Case("SPV_KHR_ray_query", Extension::KHR_ray_query)
       .Default(Extension::Unknown);
 }
 
@@ -174,6 +175,8 @@ const char *FeatureManager::getExtensionName(Extension symbol) {
     return "SPV_NV_ray_tracing";
   case Extension::NV_mesh_shader:
     return "SPV_NV_mesh_shader";
+  case Extension::KHR_ray_query:
+    return "SPV_KHR_ray_query";
   default:
     break;
   }

+ 3 - 0
tools/clang/lib/SPIRV/LowerTypeVisitor.cpp

@@ -511,6 +511,9 @@ const SpirvType *LowerTypeVisitor::lowerResourceType(QualType type,
     return spvContext.getAccelerationStructureTypeNV();
   }
 
+  if (name == "RayQuery")
+    return spvContext.getRayQueryProvisionalTypeKHR();
+
   if (name == "StructuredBuffer" || name == "RWStructuredBuffer" ||
       name == "AppendStructuredBuffer" || name == "ConsumeStructuredBuffer") {
     // StructureBuffer<S> will be translated into an OpTypeStruct with one

+ 11 - 0
tools/clang/lib/SPIRV/SpirvBuilder.cpp

@@ -790,6 +790,17 @@ SpirvBuilder::createDemoteToHelperInvocationEXT(SourceLocation loc) {
   return inst;
 }
 
+SpirvInstruction *
+SpirvBuilder::createRayQueryOpsKHR(spv::Op opcode, QualType resultType,
+                                   ArrayRef<SpirvInstruction *> operands,
+                                   bool cullFlags, SourceLocation loc) {
+  assert(insertPoint && "null insert point");
+  auto *inst = new (context)
+      SpirvRayQueryOpKHR(resultType, opcode, operands, cullFlags, loc);
+  insertPoint->addInstruction(inst);
+  return inst;
+}
+
 void SpirvBuilder::addModuleProcessed(llvm::StringRef process) {
   mod->addModuleProcessed(new (context) SpirvModuleProcessed({}, process));
 }

+ 1 - 0
tools/clang/lib/SPIRV/SpirvContext.cpp

@@ -24,6 +24,7 @@ SpirvContext::SpirvContext()
   boolType = new (this) BoolType;
   samplerType = new (this) SamplerType;
   accelerationStructureTypeNV = new (this) AccelerationStructureTypeNV;
+  rayQueryProvisionalTypeKHR = new (this) RayQueryProvisionalTypeKHR;
 }
 
 inline uint32_t log2ForBitwidth(uint32_t bitwidth) {

+ 361 - 1
tools/clang/lib/SPIRV/SpirvEmitter.cpp

@@ -22,6 +22,7 @@
 #include "llvm/ADT/StringExtras.h"
 
 #include "InitListHandler.h"
+#include "dxc/DXIL/DxilConstants.h"
 
 #ifdef SUPPORT_QUERY_GIT_COMMIT_INFO
 #include "clang/Basic/Version.h"
@@ -338,7 +339,8 @@ inline bool canActAsInParmVar(const ParmVarDecl *param) {
 /// Returns true if the given function parameter can act as shader stage
 /// output parameter.
 inline bool canActAsOutParmVar(const ParmVarDecl *param) {
-  return param->hasAttr<HLSLOutAttr>() || param->hasAttr<HLSLInOutAttr>();
+  return param->hasAttr<HLSLOutAttr>() || param->hasAttr<HLSLInOutAttr>() ||
+         hlsl::IsHLSLRayQueryType(param->getType());
 }
 
 /// Returns true if the given expression is of builtin type and can be evaluated
@@ -834,6 +836,8 @@ SpirvInstruction *SpirvEmitter::doExpr(const Expr *expr) {
   } else if (isa<CXXThisExpr>(expr)) {
     assert(curThis);
     result = curThis;
+  } else if (isa<CXXConstructExpr>(expr)) {
+    result = curThis;
   } else {
     emitError("expression class '%0' unimplemented", expr->getExprLoc())
         << expr->getStmtClassName() << expr->getSourceRange();
@@ -4098,6 +4102,48 @@ SpirvEmitter::processIntrinsicMemberCall(const CXXMemberCallExpr *expr,
               expr->getCallee()->getExprLoc())
         << expr->getMethodDecl()->getName();
     return nullptr;
+  case IntrinsicOp::MOP_TraceRayInline:
+    return processTraceRayInline(expr);
+  case IntrinsicOp::MOP_Abort:
+  case IntrinsicOp::MOP_CandidateGeometryIndex:
+  case IntrinsicOp::MOP_CandidateInstanceContributionToHitGroupIndex:
+  case IntrinsicOp::MOP_CandidateInstanceID:
+  case IntrinsicOp::MOP_CandidateInstanceIndex:
+  case IntrinsicOp::MOP_CandidateObjectRayDirection:
+  case IntrinsicOp::MOP_CandidateObjectRayOrigin:
+  case IntrinsicOp::MOP_CandidateObjectToWorld3x4:
+  case IntrinsicOp::MOP_CandidateObjectToWorld4x3:
+  case IntrinsicOp::MOP_CandidatePrimitiveIndex:
+  case IntrinsicOp::MOP_CandidateProceduralPrimitiveNonOpaque:
+  case IntrinsicOp::MOP_CandidateTriangleBarycentrics:
+  case IntrinsicOp::MOP_CandidateTriangleFrontFace:
+  case IntrinsicOp::MOP_CandidateTriangleRayT:
+  case IntrinsicOp::MOP_CandidateType:
+  case IntrinsicOp::MOP_CandidateWorldToObject3x4:
+  case IntrinsicOp::MOP_CandidateWorldToObject4x3:
+  case IntrinsicOp::MOP_CommitNonOpaqueTriangleHit:
+  case IntrinsicOp::MOP_CommitProceduralPrimitiveHit:
+  case IntrinsicOp::MOP_CommittedGeometryIndex:
+  case IntrinsicOp::MOP_CommittedInstanceContributionToHitGroupIndex:
+  case IntrinsicOp::MOP_CommittedInstanceID:
+  case IntrinsicOp::MOP_CommittedInstanceIndex:
+  case IntrinsicOp::MOP_CommittedObjectRayDirection:
+  case IntrinsicOp::MOP_CommittedObjectRayOrigin:
+  case IntrinsicOp::MOP_CommittedObjectToWorld3x4:
+  case IntrinsicOp::MOP_CommittedObjectToWorld4x3:
+  case IntrinsicOp::MOP_CommittedPrimitiveIndex:
+  case IntrinsicOp::MOP_CommittedRayT:
+  case IntrinsicOp::MOP_CommittedStatus:
+  case IntrinsicOp::MOP_CommittedTriangleBarycentrics:
+  case IntrinsicOp::MOP_CommittedTriangleFrontFace:
+  case IntrinsicOp::MOP_CommittedWorldToObject3x4:
+  case IntrinsicOp::MOP_CommittedWorldToObject4x3:
+  case IntrinsicOp::MOP_Proceed:
+  case IntrinsicOp::MOP_RayFlags:
+  case IntrinsicOp::MOP_RayTMin:
+  case IntrinsicOp::MOP_WorldRayDirection:
+  case IntrinsicOp::MOP_WorldRayOrigin:
+    return processRayQueryIntrinsics(expr, opcode);
   default:
     emitError("intrinsic '%0' method unimplemented",
               expr->getCallee()->getExprLoc())
@@ -5138,6 +5184,10 @@ void SpirvEmitter::storeValue(SpirvInstruction *lhsPtr,
     // let SPIRV-Tools opt to do the legalization work.
     //
     // Note: legalization specific code
+    if (hlsl::IsHLSLRayQueryType(lhsValType)) {
+      emitError("store value of type %0 is unsupported", {}) << lhsValType;
+      return;
+    }
     spvBuilder.createStore(lhsPtr, rhsVal, loc);
     needsLegalization = true;
   } else if (isAKindOfStructuredOrByteBuffer(lhsValType)) {
@@ -11315,5 +11365,315 @@ void SpirvEmitter::addFunctionToWorkQueue(hlsl::DXIL::ShaderKind shaderKind,
   }
 }
 
+SpirvInstruction *
+SpirvEmitter::processTraceRayInline(const CXXMemberCallExpr *expr) {
+  emitWarning("SPV_KHR_ray_query is currently a provisional extension and might"
+              "change in ways that are not backwards compatible",
+              expr->getExprLoc());
+  const auto object = expr->getImplicitObjectArgument();
+  uint32_t templateFlags = hlsl::GetHLSLResourceTemplateUInt(object->getType());
+  const auto constFlags = spvBuilder.getConstantInt(
+      astContext.UnsignedIntTy, llvm::APInt(32, templateFlags));
+
+  SpirvInstruction *rayqueryObj = loadIfAliasVarRef(object);
+
+  const auto args = expr->getArgs();
+
+  if (expr->getNumArgs() != 4) {
+    emitError("invalid number of arguments to RayQueryInitialize",
+              expr->getExprLoc());
+  }
+
+  // HLSL Func
+  // void RayQuery::TraceRayInline(
+  //      RaytracingAccelerationStructure AccelerationStructure,
+  //      uint RayFlags,
+  //      uint InstanceInclusionMask,
+  //      RayDesc Ray);
+
+  // void OpRayQueryInitializeKHR ( <id> RayQuery,
+  //                               <id> Acceleration Structure
+  //                               <id> RayFlags
+  //                               <id> CullMask
+  //                               <id> RayOrigin
+  //                               <id> RayTmin
+  //                               <id> RayDirection
+  //                               <id> Ray Tmax)
+
+  const auto accelStructure = doExpr(args[0]);
+  SpirvInstruction *rayFlags = nullptr;
+
+  if (rayFlags = tryToEvaluateAsConst(args[1])) {
+    rayFlags->setRValue();
+  } else {
+    rayFlags = doExpr(args[1]);
+  }
+
+  if (auto constFlags = dyn_cast<SpirvConstantInteger>(rayFlags)) {
+    auto interRayFlags = constFlags->getValue().getZExtValue();
+    templateFlags |= interRayFlags;
+  }
+
+  bool hasCullFlags =
+      templateFlags & (uint32_t(hlsl::DXIL::RayFlag::SkipTriangles) |
+                       uint32_t(hlsl::DXIL::RayFlag::SkipProceduralPrimitives));
+
+  auto loc = args[1]->getLocStart();
+  rayFlags =
+      spvBuilder.createBinaryOp(spv::Op::OpBitwiseOr, astContext.UnsignedIntTy,
+                                constFlags, rayFlags, loc);
+  const auto cullMask = doExpr(args[2]);
+
+  // Extract the ray description to match SPIR-V
+  const auto floatType = astContext.FloatTy;
+  const auto vecType = astContext.getExtVectorType(astContext.FloatTy, 3);
+  SpirvInstruction *rayDescArg = doExpr(args[3]);
+  loc = args[3]->getLocStart();
+  const auto origin =
+      spvBuilder.createCompositeExtract(vecType, rayDescArg, {0}, loc);
+  const auto tMin =
+      spvBuilder.createCompositeExtract(floatType, rayDescArg, {1}, loc);
+  const auto direction =
+      spvBuilder.createCompositeExtract(vecType, rayDescArg, {2}, loc);
+  const auto tMax =
+      spvBuilder.createCompositeExtract(floatType, rayDescArg, {3}, loc);
+
+  llvm::SmallVector<SpirvInstruction *, 8> traceArgs = {
+      rayqueryObj, accelStructure, rayFlags,  cullMask,
+      origin,      tMin,           direction, tMax};
+
+  return spvBuilder.createRayQueryOpsKHR(spv::Op::OpRayQueryInitializeKHR,
+                                         QualType(), traceArgs, hasCullFlags,
+                                         expr->getExprLoc());
+}
+
+SpirvInstruction *
+SpirvEmitter::processRayQueryIntrinsics(const CXXMemberCallExpr *expr,
+                                        hlsl::IntrinsicOp opcode) {
+  emitWarning("SPV_KHR_ray_query is currently a provisional extension and might"
+              "change in ways that are not backwards compatible",
+              expr->getExprLoc());
+  const auto object = expr->getImplicitObjectArgument();
+  SpirvInstruction *rayqueryObj = loadIfAliasVarRef(object);
+
+  const auto args = expr->getArgs();
+
+  llvm::SmallVector<SpirvInstruction *, 8> traceArgs;
+  traceArgs.push_back(rayqueryObj);
+
+  for (uint32_t i = 0; i < expr->getNumArgs(); ++i) {
+    traceArgs.push_back(doExpr(args[i]));
+  }
+
+  spv::Op spvCode = spv::Op::Max;
+  QualType exprType = expr->getType();
+
+  exprType = exprType->isVoidType() ? QualType() : exprType;
+
+  const auto candidateIntersection =
+      spvBuilder.getConstantInt(astContext.UnsignedIntTy, llvm::APInt(32, 0));
+  const auto committedIntersection =
+      spvBuilder.getConstantInt(astContext.UnsignedIntTy, llvm::APInt(32, 1));
+
+  bool transposeMatrix = false;
+  bool logicalNot = false;
+
+  using namespace hlsl;
+  switch (opcode) {
+  case IntrinsicOp::MOP_Proceed:
+    spvCode = spv::Op::OpRayQueryProceedKHR;
+    break;
+  case IntrinsicOp::MOP_Abort:
+    spvCode = spv::Op::OpRayQueryTerminateKHR;
+    exprType = QualType();
+    break;
+  case IntrinsicOp::MOP_CandidateGeometryIndex:
+    traceArgs.push_back(candidateIntersection);
+    spvCode = spv::Op::OpRayQueryGetIntersectionGeometryIndexKHR;
+    break;
+  case IntrinsicOp::MOP_CandidateInstanceContributionToHitGroupIndex:
+    traceArgs.push_back(candidateIntersection);
+    spvCode = spv::Op::
+        OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR;
+    break;
+  case IntrinsicOp::MOP_CandidateInstanceID:
+    traceArgs.push_back(candidateIntersection);
+    spvCode = spv::Op::OpRayQueryGetIntersectionInstanceCustomIndexKHR;
+    break;
+  case IntrinsicOp::MOP_CandidateInstanceIndex:
+    traceArgs.push_back(candidateIntersection);
+    spvCode = spv::Op::OpRayQueryGetIntersectionInstanceIdKHR;
+    break;
+  case IntrinsicOp::MOP_CandidateObjectRayDirection:
+    traceArgs.push_back(candidateIntersection);
+    spvCode = spv::Op::OpRayQueryGetIntersectionObjectRayDirectionKHR;
+    break;
+  case IntrinsicOp::MOP_CandidateObjectRayOrigin:
+    traceArgs.push_back(candidateIntersection);
+    spvCode = spv::Op::OpRayQueryGetIntersectionObjectRayOriginKHR;
+    break;
+  case IntrinsicOp::MOP_CandidateObjectToWorld3x4:
+    spvCode = spv::Op::OpRayQueryGetIntersectionObjectToWorldKHR;
+    traceArgs.push_back(candidateIntersection);
+    transposeMatrix = true;
+    break;
+  case IntrinsicOp::MOP_CandidateObjectToWorld4x3:
+    spvCode = spv::Op::OpRayQueryGetIntersectionObjectToWorldKHR;
+    traceArgs.push_back(candidateIntersection);
+    break;
+  case IntrinsicOp::MOP_CandidatePrimitiveIndex:
+    traceArgs.push_back(candidateIntersection);
+    spvCode = spv::Op::OpRayQueryGetIntersectionPrimitiveIndexKHR;
+    break;
+  case IntrinsicOp::MOP_CandidateProceduralPrimitiveNonOpaque:
+    spvCode = spv::Op::OpRayQueryGetIntersectionCandidateAABBOpaqueKHR;
+    logicalNot = true;
+    break;
+  case IntrinsicOp::MOP_CandidateTriangleBarycentrics:
+    traceArgs.push_back(candidateIntersection);
+    spvCode = spv::Op::OpRayQueryGetIntersectionBarycentricsKHR;
+    break;
+  case IntrinsicOp::MOP_CandidateTriangleFrontFace:
+    traceArgs.push_back(candidateIntersection);
+    spvCode = spv::Op::OpRayQueryGetIntersectionFrontFaceKHR;
+    break;
+  case IntrinsicOp::MOP_CandidateTriangleRayT:
+    traceArgs.push_back(candidateIntersection);
+    spvCode = spv::Op::OpRayQueryGetIntersectionTKHR;
+    break;
+  case IntrinsicOp::MOP_CandidateType:
+    spvCode = spv::Op::OpRayQueryGetIntersectionTypeKHR;
+    traceArgs.push_back(candidateIntersection);
+    break;
+  case IntrinsicOp::MOP_CandidateWorldToObject4x3:
+    spvCode = spv::Op::OpRayQueryGetIntersectionWorldToObjectKHR;
+    traceArgs.push_back(candidateIntersection);
+    break;
+  case IntrinsicOp::MOP_CandidateWorldToObject3x4:
+    spvCode = spv::Op::OpRayQueryGetIntersectionWorldToObjectKHR;
+    traceArgs.push_back(candidateIntersection);
+    transposeMatrix = true;
+    break;
+  case IntrinsicOp::MOP_CommitNonOpaqueTriangleHit:
+    spvCode = spv::Op::OpRayQueryConfirmIntersectionKHR;
+    exprType = QualType();
+    break;
+  case IntrinsicOp::MOP_CommitProceduralPrimitiveHit:
+    spvCode = spv::Op::OpRayQueryGenerateIntersectionKHR;
+    exprType = QualType();
+    break;
+  case IntrinsicOp::MOP_CommittedGeometryIndex:
+    spvCode = spv::Op::OpRayQueryGetIntersectionGeometryIndexKHR;
+    traceArgs.push_back(committedIntersection);
+    break;
+  case IntrinsicOp::MOP_CommittedInstanceContributionToHitGroupIndex:
+    spvCode = spv::Op::
+        OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR;
+    traceArgs.push_back(committedIntersection);
+    break;
+  case IntrinsicOp::MOP_CommittedInstanceID:
+    spvCode = spv::Op::OpRayQueryGetIntersectionInstanceCustomIndexKHR;
+    traceArgs.push_back(committedIntersection);
+    break;
+  case IntrinsicOp::MOP_CommittedInstanceIndex:
+    spvCode = spv::Op::OpRayQueryGetIntersectionInstanceIdKHR;
+    traceArgs.push_back(committedIntersection);
+    break;
+  case IntrinsicOp::MOP_CommittedObjectRayDirection:
+    spvCode = spv::Op::OpRayQueryGetIntersectionObjectRayDirectionKHR;
+    traceArgs.push_back(committedIntersection);
+    break;
+  case IntrinsicOp::MOP_CommittedObjectRayOrigin:
+    spvCode = spv::Op::OpRayQueryGetIntersectionObjectRayOriginKHR;
+    traceArgs.push_back(committedIntersection);
+    break;
+  case IntrinsicOp::MOP_CommittedObjectToWorld3x4:
+    spvCode = spv::Op::OpRayQueryGetIntersectionObjectToWorldKHR;
+    traceArgs.push_back(committedIntersection);
+    transposeMatrix = true;
+    break;
+  case IntrinsicOp::MOP_CommittedObjectToWorld4x3:
+    spvCode = spv::Op::OpRayQueryGetIntersectionObjectToWorldKHR;
+    traceArgs.push_back(committedIntersection);
+    break;
+  case IntrinsicOp::MOP_CommittedPrimitiveIndex:
+    spvCode = spv::Op::OpRayQueryGetIntersectionPrimitiveIndexKHR;
+    traceArgs.push_back(committedIntersection);
+    break;
+  case IntrinsicOp::MOP_CommittedRayT:
+    spvCode = spv::Op::OpRayQueryGetIntersectionTKHR;
+    traceArgs.push_back(committedIntersection);
+    break;
+  case IntrinsicOp::MOP_CommittedStatus:
+    spvCode = spv::Op::OpRayQueryGetIntersectionTypeKHR;
+    traceArgs.push_back(committedIntersection);
+    break;
+  case IntrinsicOp::MOP_CommittedTriangleBarycentrics:
+    spvCode = spv::Op::OpRayQueryGetIntersectionBarycentricsKHR;
+    traceArgs.push_back(committedIntersection);
+    break;
+  case IntrinsicOp::MOP_CommittedTriangleFrontFace:
+    spvCode = spv::Op::OpRayQueryGetIntersectionFrontFaceKHR;
+    traceArgs.push_back(committedIntersection);
+    break;
+  case IntrinsicOp::MOP_CommittedWorldToObject3x4:
+    spvCode = spv::Op::OpRayQueryGetIntersectionWorldToObjectKHR;
+    traceArgs.push_back(committedIntersection);
+    transposeMatrix = true;
+    break;
+  case IntrinsicOp::MOP_CommittedWorldToObject4x3:
+    spvCode = spv::Op::OpRayQueryGetIntersectionWorldToObjectKHR;
+    traceArgs.push_back(committedIntersection);
+    break;
+  case IntrinsicOp::MOP_RayFlags:
+    spvCode = spv::Op::OpRayQueryGetRayFlagsKHR;
+    break;
+  case IntrinsicOp::MOP_RayTMin:
+    spvCode = spv::Op::OpRayQueryGetRayTMinKHR;
+    break;
+  case IntrinsicOp::MOP_WorldRayDirection:
+    spvCode = spv::Op::OpRayQueryGetWorldRayDirectionKHR;
+    break;
+  case IntrinsicOp::MOP_WorldRayOrigin:
+    spvCode = spv::Op::OpRayQueryGetWorldRayOriginKHR;
+    break;
+  default:
+    emitError("intrinsic '%0' method unimplemented",
+              expr->getCallee()->getExprLoc())
+        << expr->getDirectCallee()->getName();
+    return nullptr;
+  }
+
+  if (transposeMatrix) {
+    assert(hlsl::IsHLSLMatType(exprType) && "intrinsic should be matrix");
+    const clang::Type *type = exprType.getCanonicalType().getTypePtr();
+    const RecordType *RT = cast<RecordType>(type);
+    const ClassTemplateSpecializationDecl *templateSpecDecl =
+        cast<ClassTemplateSpecializationDecl>(RT->getDecl());
+    ClassTemplateDecl *templateDecl =
+        templateSpecDecl->getSpecializedTemplate();
+    const auto retType = exprType;
+    exprType = getHLSLMatrixType(astContext, theCompilerInstance.getSema(),
+                                 templateDecl, astContext.FloatTy, 4, 3);
+  }
+
+  const auto loc = expr->getExprLoc();
+  SpirvInstruction *retVal =
+      spvBuilder.createRayQueryOpsKHR(spvCode, exprType, traceArgs, false, loc);
+
+  if (transposeMatrix) {
+    retVal = spvBuilder.createUnaryOp(spv::Op::OpTranspose, expr->getType(),
+                                      retVal, loc);
+  }
+
+  if (logicalNot) {
+    retVal = spvBuilder.createUnaryOp(spv::Op::OpLogicalNot, expr->getType(),
+                                      retVal, loc);
+  }
+
+  retVal->setRValue();
+  return retVal;
+}
+
 } // end namespace spirv
 } // end namespace clang

+ 7 - 0
tools/clang/lib/SPIRV/SpirvEmitter.h

@@ -553,6 +553,13 @@ private:
   /// Process mesh shader intrinsics.
   void processMeshOutputCounts(const CallExpr *callExpr);
 
+  /// Process ray query traceinline intrinsics.
+  SpirvInstruction *processTraceRayInline(const CXXMemberCallExpr *expr);
+
+  /// Process ray query intrinsics
+  SpirvInstruction *processRayQueryIntrinsics(const CXXMemberCallExpr *expr,
+                                              hlsl::IntrinsicOp opcode);
+
 private:
   /// Returns the <result-id> for constant value 0 of the given type.
   SpirvConstant *getValueZero(QualType type);

+ 7 - 0
tools/clang/lib/SPIRV/SpirvInstruction.cpp

@@ -82,6 +82,7 @@ DEFINE_INVOKE_VISITOR_FOR_CLASS(SpirvVectorShuffle)
 DEFINE_INVOKE_VISITOR_FOR_CLASS(SpirvArrayLength)
 DEFINE_INVOKE_VISITOR_FOR_CLASS(SpirvRayTracingOpNV)
 DEFINE_INVOKE_VISITOR_FOR_CLASS(SpirvDemoteToHelperInvocationEXT)
+DEFINE_INVOKE_VISITOR_FOR_CLASS(SpirvRayQueryOpKHR)
 
 #undef DEFINE_INVOKE_VISITOR_FOR_CLASS
 
@@ -766,5 +767,11 @@ SpirvDemoteToHelperInvocationEXT::SpirvDemoteToHelperInvocationEXT(
                        spv::Op::OpDemoteToHelperInvocationEXT, /*QualType*/ {},
                        loc) {}
 
+SpirvRayQueryOpKHR::SpirvRayQueryOpKHR(
+    QualType resultType, spv::Op opcode,
+    llvm::ArrayRef<SpirvInstruction *> vecOperands, bool flags,
+    SourceLocation loc)
+    : SpirvInstruction(IK_RayQueryOpKHR, opcode, resultType, loc),
+      operands(vecOperands.begin(), vecOperands.end()), cullFlags(flags) {}
 } // namespace spirv
 } // namespace clang

+ 9 - 0
tools/clang/test/CodeGenSPIRV/rayquery_assign.cs.hlsl

@@ -0,0 +1,9 @@
+// Run: %dxc -T cs_6_5 -E CS
+// CHECK:  error: store value of type 'RayQuery<RAY_FLAG_FORCE_OPAQUE | RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH>' is unsupported
+
+[numThreads(1,1,1)]
+void CS()
+{
+    RayQuery<RAY_FLAG_FORCE_OPAQUE|RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH> q;
+    RayQuery<RAY_FLAG_FORCE_OPAQUE|RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH> b = q;
+}

+ 63 - 0
tools/clang/test/CodeGenSPIRV/rayquery_init_ds.hlsl

@@ -0,0 +1,63 @@
+// RUN: %dxc -T ds_6_5 -E main
+// CHECK:  OpCapability RayQueryProvisionalKHR
+// CHECK:  OpExtension "SPV_KHR_ray_query"
+
+struct VSSceneIn {
+  float3 pos : POSITION;
+};
+
+struct PSSceneIn {
+  float4 pos : SV_Position;
+};
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// Simple forwarding Tessellation shaders
+
+struct HSPerVertexData {
+  // This is just the original vertex verbatim. In many real life cases this would be a
+  // control point instead
+  PSSceneIn v;
+};
+
+struct HSPerPatchData {
+  // We at least have to specify tess factors per patch
+  // As we're tesselating triangles, there will be 4 tess factors
+  // In real life case this might contain face normal, for example
+  float edges[3] : SV_TessFactor;
+  float inside : SV_InsideTessFactor;
+};
+
+RaytracingAccelerationStructure AccelerationStructure : register(t0);
+RayDesc MakeRayDesc()
+{
+    RayDesc desc;
+    desc.Origin = float3(0,0,0);
+    desc.Direction = float3(1,0,0);
+    desc.TMin = 0.0f;
+    desc.TMax = 9999.0;
+    return desc;
+}
+void doInitialize(RayQuery<RAY_FLAG_FORCE_OPAQUE> query, RayDesc ray)
+{
+    query.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_NON_OPAQUE,0xFF,ray);
+}
+
+// domain shader that actually outputs the triangle vertices
+[domain("tri")] PSSceneIn main(const float3 bary
+                               : SV_DomainLocation,
+                                 const OutputPatch<HSPerVertexData, 3> patch,
+                                 const HSPerPatchData perPatchData) {
+  PSSceneIn v;
+  v.pos = patch[0].v.pos * bary.x + patch[1].v.pos * bary.y + patch[2].v.pos * bary.z + perPatchData.edges[1];
+
+    RayQuery<RAY_FLAG_FORCE_OPAQUE> q;
+    RayDesc ray = MakeRayDesc();
+// CHECK:  [[accel:%\d+]] = OpLoad %accelerationStructureNV %AccelerationStructure
+// CHECK:  OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_1 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999
+
+    q.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_OPAQUE, 0xFF, ray);
+// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_3 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999
+    doInitialize(q, ray);
+
+  return v;
+}

+ 43 - 0
tools/clang/test/CodeGenSPIRV/rayquery_init_gs.hlsl

@@ -0,0 +1,43 @@
+// RUN: %dxc -T gs_6_5 -E main
+// CHECK:  OpCapability RayQueryProvisionalKHR
+// CHECK:  OpExtension "SPV_KHR_ray_query
+
+struct Out
+{
+  float4 pos : SV_Position;
+};
+
+struct Empty{};
+
+RaytracingAccelerationStructure AccelerationStructure : register(t0);
+RayDesc MakeRayDesc()
+{
+    RayDesc desc;
+    desc.Origin = float3(0,0,0);
+    desc.Direction = float3(1,0,0);
+    desc.TMin = 0.0f;
+    desc.TMax = 9999.0;
+    return desc;
+}
+void doInitialize(RayQuery<RAY_FLAG_FORCE_OPAQUE> query, RayDesc ray)
+{
+    query.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_NON_OPAQUE,0xFF,ray);
+}
+
+[maxvertexcount(3)]
+void main(line Empty e[4], inout PointStream<Out> OutputStream0)
+{
+  RayQuery<RAY_FLAG_FORCE_OPAQUE> q;
+  RayDesc ray = MakeRayDesc();
+// CHECK:  [[accel:%\d+]] = OpLoad %accelerationStructureNV %AccelerationStructure
+// CHECK:  OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_1 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999
+
+  q.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_OPAQUE, 0xFF, ray);
+// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_3 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999
+  doInitialize(q, ray);
+
+  Out output = (Out)0;
+
+  OutputStream0.Append(output);
+  OutputStream0.RestartStrip();
+}

+ 75 - 0
tools/clang/test/CodeGenSPIRV/rayquery_init_hs.hlsl

@@ -0,0 +1,75 @@
+// Run: %dxc -T hs_6_5 -E main
+// CHECK:  OpCapability RayQueryProvisionalKHR
+// CHECK:  OpCapability RayTraversalPrimitiveCullingProvisionalKHR
+// CHECK:  OpExtension "SPV_KHR_ray_query"
+
+#define MAX_POINTS 3
+
+// Input control point
+struct VS_CONTROL_POINT_OUTPUT
+{
+  float3 vPosition : WORLDPOS;
+};
+
+// Output control point
+struct CONTROL_POINT
+{
+  float3 vPosition	: BEZIERPOS;
+};
+
+// Output patch constant data.
+struct HS_CONSTANT_DATA_OUTPUT
+{
+  float Edges[4]        : SV_TessFactor;
+  float Inside[2]       : SV_InsideTessFactor;
+};
+
+// Patch Constant Function
+HS_CONSTANT_DATA_OUTPUT mainConstant(InputPatch<VS_CONTROL_POINT_OUTPUT, MAX_POINTS> ip) {
+  HS_CONSTANT_DATA_OUTPUT Output;
+
+  // Must initialize Edges and Inside; otherwise HLSL validation will fail.
+  Output.Edges[0]  = 1.0;
+  Output.Edges[1]  = 2.0;
+  Output.Edges[2]  = 3.0;
+  Output.Edges[3]  = 4.0;
+  Output.Inside[0] = 5.0;
+  Output.Inside[1] = 6.0;
+
+  return Output;
+}
+
+
+
+RaytracingAccelerationStructure AccelerationStructure : register(t0);
+RayDesc MakeRayDesc()
+{
+    RayDesc desc;
+    desc.Origin = float3(0,0,0);
+    desc.Direction = float3(1,0,0);
+    desc.TMin = 0.0f;
+    desc.TMax = 9999.0;
+    return desc;
+}
+void doInitialize(RayQuery<RAY_FLAG_FORCE_OPAQUE|RAY_FLAG_SKIP_TRIANGLES> query, RayDesc ray)
+{
+    query.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_NON_OPAQUE,0xFF,ray);
+}
+
+[outputcontrolpoints(MAX_POINTS)]
+[patchconstantfunc("mainConstant")]
+CONTROL_POINT main(InputPatch<VS_CONTROL_POINT_OUTPUT, MAX_POINTS> ip, uint cpid : SV_OutputControlPointID) {
+// CHECK:  %rayQueryProvisionalKHR = OpTypeRayQueryProvisionalKHR
+// CHECK:  %_ptr_Function_rayQueryProvisionalKHR = OpTypePointer Function %rayQueryProvisionalKHR
+// CHECK:  [[rayquery:%\d+]] = OpVariable %_ptr_Function_rayQueryProvisionalKHR Function
+    RayQuery<RAY_FLAG_FORCE_OPAQUE|RAY_FLAG_SKIP_TRIANGLES> q;
+    RayDesc ray = MakeRayDesc();
+// CHECK:  [[accel:%\d+]] = OpLoad %accelerationStructureNV %AccelerationStructure
+// CHECK:  OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_517 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999
+
+    q.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_OPAQUE, 0xFF, ray);
+// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_259 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999
+    doInitialize(q, ray);
+    CONTROL_POINT result;
+    return result;
+}

+ 33 - 0
tools/clang/test/CodeGenSPIRV/rayquery_init_ps.hlsl

@@ -0,0 +1,33 @@
+// RUN: %dxc -E main -T ps_6_5
+
+// RUN: %dxc -T gs_6_5 -E main
+// CHECK:  OpCapability RayQueryProvisionalKHR
+// CHECK:  OpExtension "SPV_KHR_ray_query
+
+RaytracingAccelerationStructure AccelerationStructure : register(t0);
+RayDesc MakeRayDesc()
+{
+    RayDesc desc;
+    desc.Origin = float3(0,0,0);
+    desc.Direction = float3(1,0,0);
+    desc.TMin = 0.0f;
+    desc.TMax = 9999.0;
+    return desc;
+}
+void doInitialize(RayQuery<RAY_FLAG_FORCE_OPAQUE> query, RayDesc ray)
+{
+    query.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_NON_OPAQUE,0xFF,ray);
+}
+
+uint4 main() : SV_Target
+{
+  RayQuery<RAY_FLAG_FORCE_OPAQUE> q;
+  RayDesc ray = MakeRayDesc();
+// CHECK:  [[accel:%\d+]] = OpLoad %accelerationStructureNV %AccelerationStructure
+// CHECK:  OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_1 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999
+
+  q.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_OPAQUE, 0xFF, ray);
+// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_3 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999
+  doInitialize(q, ray);
+  return float4(1.0, 0.0, 0.0, 1.0);
+}

+ 42 - 0
tools/clang/test/CodeGenSPIRV/rayquery_init_rahit.hlsl

@@ -0,0 +1,42 @@
+// Run: %dxc -T lib_6_3
+// CHECK:  OpCapability RayTracingProvisionalKHR
+// CHECK:  OpCapability RayQueryProvisionalKHR
+// CHECK:  OpExtension "SPV_KHR_ray_tracing"
+// CHECK:  OpExtension "SPV_KHR_ray_query"
+
+RaytracingAccelerationStructure AccelerationStructure : register(t0);
+RayDesc MakeRayDesc()
+{
+    RayDesc desc;
+    desc.Origin = float3(0,0,0);
+    desc.Direction = float3(1,0,0);
+    desc.TMin = 0.0f;
+    desc.TMax = 9999.0;
+    return desc;
+}
+void doInitialize(RayQuery<RAY_FLAG_FORCE_OPAQUE> query, RayDesc ray)
+{
+    query.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_NON_OPAQUE,0xFF,ray);
+}
+
+struct Payload
+{
+  float4 color;
+};
+// CHECK:  OpTypePointer HitAttributeNV %Attribute
+struct Attribute
+{
+  float2 bary;
+};
+
+[shader("anyhit")]
+void main(inout Payload MyPayload, in Attribute MyAttr) {
+  Payload myPayload = { float4(0.0f,0.0f,0.0f,0.0f) };
+  RayQuery<RAY_FLAG_FORCE_OPAQUE> q;
+  RayDesc ray = MakeRayDesc();
+// CHECK:  [[accel:%\d+]] = OpLoad %accelerationStructureNV %AccelerationStructure
+// CHECK:  OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_1 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999
+  q.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_OPAQUE, 0xFF, ray);
+// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_3 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999
+  doInitialize(q, ray);
+}

+ 37 - 0
tools/clang/test/CodeGenSPIRV/rayquery_init_rcall.hlsl

@@ -0,0 +1,37 @@
+// Run: %dxc -T lib_6_3
+// CHECK:  OpCapability RayTracingProvisionalKHR
+// CHECK:  OpCapability RayQueryProvisionalKHR
+// CHECK:  OpExtension "SPV_KHR_ray_tracing"
+// CHECK:  OpExtension "SPV_KHR_ray_query"
+
+RaytracingAccelerationStructure AccelerationStructure : register(t0);
+RayDesc MakeRayDesc()
+{
+    RayDesc desc;
+    desc.Origin = float3(0,0,0);
+    desc.Direction = float3(1,0,0);
+    desc.TMin = 0.0f;
+    desc.TMax = 9999.0;
+    return desc;
+}
+void doInitialize(RayQuery<RAY_FLAG_FORCE_OPAQUE> query, RayDesc ray)
+{
+    query.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_NON_OPAQUE,0xFF,ray);
+}
+
+struct Payload
+{
+  float4 color;
+};
+
+[shader("miss")]
+void main(inout Payload MyPayload) {
+  Payload myPayload = { float4(0.0f,0.0f,0.0f,0.0f) };
+  RayQuery<RAY_FLAG_FORCE_OPAQUE> q;
+  RayDesc ray = MakeRayDesc();
+// CHECK:  [[accel:%\d+]] = OpLoad %accelerationStructureNV %AccelerationStructure
+// CHECK:  OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_1 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999
+  q.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_OPAQUE, 0xFF, ray);
+// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_3 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999
+  doInitialize(q, ray);
+}

+ 42 - 0
tools/clang/test/CodeGenSPIRV/rayquery_init_rchit.hlsl

@@ -0,0 +1,42 @@
+// Run: %dxc -T lib_6_3
+// CHECK:  OpCapability RayTracingProvisionalKHR
+// CHECK:  OpCapability RayQueryProvisionalKHR
+// CHECK:  OpExtension "SPV_KHR_ray_tracing"
+// CHECK:  OpExtension "SPV_KHR_ray_query"
+
+RaytracingAccelerationStructure AccelerationStructure : register(t0);
+RayDesc MakeRayDesc()
+{
+    RayDesc desc;
+    desc.Origin = float3(0,0,0);
+    desc.Direction = float3(1,0,0);
+    desc.TMin = 0.0f;
+    desc.TMax = 9999.0;
+    return desc;
+}
+void doInitialize(RayQuery<RAY_FLAG_FORCE_OPAQUE> query, RayDesc ray)
+{
+    query.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_NON_OPAQUE,0xFF,ray);
+}
+
+struct Payload
+{
+  float4 color;
+};
+// CHECK:  OpTypePointer HitAttributeNV %Attribute
+struct Attribute
+{
+  float2 bary;
+};
+
+[shader("closesthit")]
+void main(inout Payload MyPayload, in Attribute MyAttr) {
+  Payload myPayload = { float4(0.0f,0.0f,0.0f,0.0f) };
+  RayQuery<RAY_FLAG_FORCE_OPAQUE> q;
+  RayDesc ray = MakeRayDesc();
+// CHECK:  [[accel:%\d+]] = OpLoad %accelerationStructureNV %AccelerationStructure
+// CHECK:  OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_1 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999
+  q.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_OPAQUE, 0xFF, ray);
+// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_3 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999
+  doInitialize(q, ray);
+}

+ 42 - 0
tools/clang/test/CodeGenSPIRV/rayquery_init_rgen.hlsl

@@ -0,0 +1,42 @@
+// Run: %dxc -T lib_6_3
+// CHECK:  OpCapability RayTracingProvisionalKHR
+// CHECK:  OpCapability RayQueryProvisionalKHR
+// CHECK:  OpExtension "SPV_KHR_ray_tracing"
+// CHECK:  OpExtension "SPV_KHR_ray_query"
+
+// CHECK-COUNT-1: [[rs:%\d+]] = OpTypeAccelerationStructureNV
+RaytracingAccelerationStructure AccelerationStructure : register(t0);
+RayDesc MakeRayDesc()
+{
+    RayDesc desc;
+    desc.Origin = float3(0,0,0);
+    desc.Direction = float3(1,0,0);
+    desc.TMin = 0.0f;
+    desc.TMax = 9999.0;
+    return desc;
+}
+void doInitialize(RayQuery<RAY_FLAG_FORCE_OPAQUE> query, RayDesc ray)
+{
+    query.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_NON_OPAQUE,0xFF,ray);
+}
+
+struct Payload
+{
+  float4 color;
+};
+
+
+[shader("raygeneration")]
+void main() {
+
+  Payload myPayload = { float4(0.0f,0.0f,0.0f,0.0f) };
+  RayQuery<RAY_FLAG_FORCE_OPAQUE> q;
+  RayDesc ray = MakeRayDesc();
+// CHECK:  [[accel:%\d+]] = OpLoad %accelerationStructureNV %AccelerationStructure
+// CHECK:  OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_1 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999
+  q.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_OPAQUE, 0xFF, ray);
+// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_3 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999
+  doInitialize(q, ray);
+// CHECK: OpTraceNV {{%\d+}} %uint_0 %uint_255 %uint_0 %uint_1 %uint_0 {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} %uint_0
+  TraceRay(AccelerationStructure, 0x0, 0xff, 0, 1, 0, ray, myPayload);
+}

+ 41 - 0
tools/clang/test/CodeGenSPIRV/rayquery_init_rint.hlsl

@@ -0,0 +1,41 @@
+// Run: %dxc -T lib_6_3
+// CHECK:  OpCapability RayTracingProvisionalKHR
+// CHECK:  OpCapability RayQueryProvisionalKHR
+// CHECK:  OpExtension "SPV_KHR_ray_tracing"
+// CHECK:  OpExtension "SPV_KHR_ray_query"
+
+RaytracingAccelerationStructure AccelerationStructure : register(t0);
+RayDesc MakeRayDesc()
+{
+    RayDesc desc;
+    desc.Origin = float3(0,0,0);
+    desc.Direction = float3(1,0,0);
+    desc.TMin = 0.0f;
+    desc.TMax = 9999.0;
+    return desc;
+}
+void doInitialize(RayQuery<RAY_FLAG_FORCE_OPAQUE> query, RayDesc ray)
+{
+    query.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_NON_OPAQUE,0xFF,ray);
+}
+
+struct CallData
+{
+  float4 data;
+};
+
+[shader("callable")]
+void main() {
+
+  RayQuery<RAY_FLAG_FORCE_OPAQUE> q;
+  RayDesc ray = MakeRayDesc();
+// CHECK:  [[accel:%\d+]] = OpLoad %accelerationStructureNV %AccelerationStructure
+// CHECK:  OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_1 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999
+  q.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_OPAQUE, 0xFF, ray);
+// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_3 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999
+  doInitialize(q, ray);
+
+  Attribute myHitAttribute = { float2(0.0f,0.0f) };
+// CHECK: OpReportIntersectionKHR %bool %float_0 %uint_0
+  ReportHit(0.0f, 0U, myHitAttribute);
+}

+ 37 - 0
tools/clang/test/CodeGenSPIRV/rayquery_init_rmiss.hlsl

@@ -0,0 +1,37 @@
+// Run: %dxc -T lib_6_3
+// CHECK:  OpCapability RayTracingProvisionalKHR
+// CHECK:  OpCapability RayQueryProvisionalKHR
+// CHECK:  OpExtension "SPV_KHR_ray_tracing"
+// CHECK:  OpExtension "SPV_KHR_ray_query"
+
+RaytracingAccelerationStructure AccelerationStructure : register(t0);
+RayDesc MakeRayDesc()
+{
+    RayDesc desc;
+    desc.Origin = float3(0,0,0);
+    desc.Direction = float3(1,0,0);
+    desc.TMin = 0.0f;
+    desc.TMax = 9999.0;
+    return desc;
+}
+void doInitialize(RayQuery<RAY_FLAG_FORCE_OPAQUE> query, RayDesc ray)
+{
+    query.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_NON_OPAQUE,0xFF,ray);
+}
+
+struct Payload
+{
+  float4 color;
+};
+
+[shader("miss")]
+void main(inout Payload MyPayload) {
+  Payload myPayload = { float4(0.0f,0.0f,0.0f,0.0f) };
+  RayQuery<RAY_FLAG_FORCE_OPAQUE> q;
+  RayDesc ray = MakeRayDesc();
+// CHECK:  [[accel:%\d+]] = OpLoad %accelerationStructureNV %AccelerationStructure
+// CHECK:  OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_1 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999
+  q.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_OPAQUE, 0xFF, ray);
+// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_3 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999
+  doInitialize(q, ray);
+}

+ 45 - 0
tools/clang/test/CodeGenSPIRV/rayquery_init_vs.hlsl

@@ -0,0 +1,45 @@
+// Run: %dxc -T vs_6_5 -E main
+// CHECK:  OpCapability RayQueryProvisionalKHR
+// CHECK:  OpCapability RayTraversalPrimitiveCullingProvisionalKHR
+// CHECK:  OpExtension "SPV_KHR_ray_query"
+
+
+RaytracingAccelerationStructure AccelerationStructure : register(t0);
+RWByteAddressBuffer log : register(u0);
+
+RayDesc MakeRayDesc()
+{
+    RayDesc desc;
+    desc.Origin = float3(0,0,0);
+    desc.Direction = float3(1,0,0);
+    desc.TMin = 0.0f;
+    desc.TMax = 9999.0;
+    return desc;
+}
+
+
+void DoSomething()
+{
+    log.Store(0,1);
+}
+
+void doInitialize(RayQuery<RAY_FLAG_FORCE_OPAQUE|RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH> query, RayDesc ray)
+{
+    query.TraceRayInline(AccelerationStructure,RAY_FLAG_NONE,0xFF,ray);
+}
+
+
+void main()
+{
+// CHECK:  %rayQueryProvisionalKHR = OpTypeRayQueryProvisionalKHR
+// CHECK:  %_ptr_Function_rayQueryProvisionalKHR = OpTypePointer Function %rayQueryProvisionalKHR
+// CHECK:  [[rayquery:%\d+]] = OpVariable %_ptr_Function_rayQueryProvisionalKHR Function
+    RayQuery<RAY_FLAG_FORCE_OPAQUE|RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH> q;
+    RayDesc ray = MakeRayDesc();
+// CHECK:  [[accel:%\d+]] = OpLoad %accelerationStructureNV %AccelerationStructure
+// CHECK:  OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_517 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999
+
+    q.TraceRayInline(AccelerationStructure,RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES, 0xFF, ray);
+// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_5 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999
+    doInitialize(q, ray);
+}

+ 206 - 0
tools/clang/test/CodeGenSPIRV/rayquery_tryAllOps.cs.hlsl

@@ -0,0 +1,206 @@
+// Run: dxc -T cs_6_5 -E CS
+// CHECK:  OpCapability RayQueryProvisionalKHR
+// CHECK:  OpExtension "SPV_KHR_ray_query"
+
+RaytracingAccelerationStructure AccelerationStructure : register(t0);
+RWByteAddressBuffer log : register(u0);
+
+RayDesc MakeRayDesc()
+{
+    RayDesc desc;
+    desc.Origin = float3(0,0,0);
+    desc.Direction = float3(1,0,0);
+    desc.TMin = 0.0f;
+    desc.TMax = 9999.0;
+    return desc;
+}
+
+void DoSomething()
+{
+    log.Store(0,1);
+}
+
+[numThreads(1,1,1)]
+void CS()
+{
+    RayQuery<RAY_FLAG_FORCE_OPAQUE|RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH> q;
+    RayDesc ray = MakeRayDesc();
+    q.TraceRayInline(AccelerationStructure,RAY_FLAG_NONE,0xFF,ray);
+    float4x3 mat4x3;
+    float3x4 mat3x4;
+// CHECK:  [[rayquery:%\d+]] = OpVariable %_ptr_Function_rayQueryProvisionalKHR Function
+// CHECK:  OpRayQueryProceedKHR %bool [[rayquery]]
+    while(q.Proceed())
+    {
+// CHECK:  OpRayQueryGetIntersectionTypeKHR %uint [[rayquery]] %uint_0
+        switch(q.CandidateType())
+        {
+        case CANDIDATE_NON_OPAQUE_TRIANGLE:
+            q.Abort();
+// CHECK:  OpRayQueryGetIntersectionObjectToWorldKHR %mat4v3float [[rayquery]] %uint_0
+            mat3x4 = q.CandidateObjectToWorld3x4();
+            mat4x3 = q.CandidateObjectToWorld4x3();
+// CHECK:  OpRayQueryConfirmIntersectionKHR [[rayquery]]
+            q.CommitNonOpaqueTriangleHit();
+// CHECK:  OpRayQueryGetIntersectionFrontFaceKHR %bool [[rayquery]] %uint_0
+            if(q.CandidateTriangleFrontFace())
+            {
+                DoSomething();
+            }
+// CHECK:  OpRayQueryGetIntersectionBarycentricsKHR %v2float [[rayquery]] %uint_0
+            if(q.CandidateTriangleBarycentrics().x == 0)
+            {
+                DoSomething();
+            }
+// CHECK:  OpRayQueryGetIntersectionGeometryIndexKHR %uint [[rayquery]] %uint_0
+            if(q.CandidateGeometryIndex())
+            {
+                DoSomething();
+            }
+// CHECK:  OpRayQueryGetIntersectionInstanceCustomIndexKHR %uint [[rayquery]] %uint_0
+            if(q.CandidateInstanceID())
+            {
+                DoSomething();
+            }
+// CHECK:  OpRayQueryGetIntersectionInstanceIdKHR %uint [[rayquery]] %uint_0
+            if(q.CandidateInstanceIndex())
+            {
+                DoSomething();
+            }
+// CHECK:  OpRayQueryGetIntersectionObjectRayDirectionKHR %v3float [[rayquery]] %uint_0
+            if(q.CandidateObjectRayDirection().x)
+            {
+                DoSomething();
+            }
+// CHECK:  OpRayQueryGetIntersectionObjectRayOriginKHR %v3float [[rayquery]] %uint_0
+            if(q.CandidateObjectRayOrigin().y)
+            {
+                DoSomething();
+            }
+// CHECK:  OpRayQueryGetIntersectionPrimitiveIndexKHR %uint [[rayquery]] %uint_0
+            if(q.CandidatePrimitiveIndex())
+            {
+                DoSomething();
+            }
+// CHECK:  OpRayQueryGetIntersectionTKHR %float [[rayquery]] %uint_0
+            if(q.CandidateTriangleRayT())
+            {
+                DoSomething();
+            }
+// CHECK:  OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR %uint [[rayquery]] %uint_0
+            if(q.CandidateInstanceContributionToHitGroupIndex())
+            {
+                DoSomething();
+            }
+            break;
+        case CANDIDATE_PROCEDURAL_PRIMITIVE:
+        {
+// CHECK:  OpRayQueryGetIntersectionWorldToObjectKHR %mat4v3float [[rayquery]] %uint_0
+            mat3x4 = q.CandidateWorldToObject3x4();
+            mat4x3 = q.CandidateWorldToObject4x3();
+// CHECK:  OpRayQueryGetIntersectionCandidateAABBOpaqueKHR %bool
+            if(q.CandidateProceduralPrimitiveNonOpaque())
+            {
+                DoSomething();
+            }
+            float t = 0.5;
+// CHECK:  OpRayQueryGenerateIntersectionKHR [[rayquery]] %float_0_5
+            q.CommitProceduralPrimitiveHit(t);
+            q.Abort();
+            break;
+        }
+        }
+    }
+    if(mat3x4[0][0] == mat4x3[0][0])
+    {
+        DoSomething();
+    }
+// CHECK:  OpRayQueryGetIntersectionTypeKHR %uint [[rayquery]] %uint_1
+    switch(q.CommittedStatus())
+    {
+    case COMMITTED_NOTHING:
+// CHECK:  OpRayQueryGetIntersectionObjectToWorldKHR %mat4v3float [[rayquery]] %uint_1
+        mat3x4 = q.CommittedObjectToWorld3x4();
+        mat4x3 = q.CommittedObjectToWorld4x3();
+        break;
+    case COMMITTED_TRIANGLE_HIT:
+// CHECK:  OpRayQueryGetIntersectionWorldToObjectKHR %mat4v3float [[rayquery]] %uint_1
+        mat3x4 = q.CommittedWorldToObject3x4();
+        mat4x3 = q.CommittedWorldToObject4x3();
+// CHECK:  OpRayQueryGetIntersectionFrontFaceKHR %bool [[rayquery]] %uint_1
+        if(q.CommittedTriangleFrontFace())
+        {
+            DoSomething();
+        }
+// CHECK:  OpRayQueryGetIntersectionBarycentricsKHR %v2float [[rayquery]] %uint_1
+        if(q.CommittedTriangleBarycentrics().y == 0)
+        {
+            DoSomething();
+        }
+// CHECK:  OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR %uint [[rayquery]] %uint_1
+        if(q.CommittedInstanceContributionToHitGroupIndex())
+        {
+            DoSomething();
+        }
+        break;
+    case COMMITTED_PROCEDURAL_PRIMITIVE_HIT:
+// CHECK:  OpRayQueryGetIntersectionGeometryIndexKHR %uint [[rayquery]] %uint_1
+        if(q.CommittedGeometryIndex())
+        {
+            DoSomething();
+        }
+// CHECK:  OpRayQueryGetIntersectionInstanceCustomIndexKHR %uint [[rayquery]] %uint_1
+        if(q.CommittedInstanceID())
+        {
+            DoSomething();
+        }
+// CHECK:  OpRayQueryGetIntersectionInstanceIdKHR %uint [[rayquery]] %uint_1
+        if(q.CommittedInstanceIndex())
+        {
+            DoSomething();
+        }
+// CHECK:  OpRayQueryGetIntersectionObjectRayDirectionKHR %v3float [[rayquery]] %uint_1
+        if(q.CommittedObjectRayDirection().z)
+        {
+            DoSomething();
+        }
+// CHECK:  OpRayQueryGetIntersectionObjectRayOriginKHR %v3float [[rayquery]] %uint_1
+        if(q.CommittedObjectRayOrigin().x)
+        {
+            DoSomething();
+        }
+// CHECK:  OpRayQueryGetIntersectionPrimitiveIndexKHR %uint [[rayquery]] %uint_1
+        if(q.CommittedPrimitiveIndex())
+        {
+            DoSomething();
+        }
+// CHECK:  OpRayQueryGetIntersectionTKHR %float [[rayquery]] %uint_1
+        if(q.CommittedRayT())
+        {
+            DoSomething();
+        }
+        break;
+    }
+    if(mat3x4[0][0] == mat4x3[0][0])
+    {
+        DoSomething();
+    }
+// CHECK:  OpRayQueryGetRayFlagsKHR %uint [[rayquery]]
+    if(q.RayFlags())
+    {
+        DoSomething();
+    }
+// CHECK:  OpRayQueryGetRayTMinKHR %float [[rayquery]]
+    if(q.RayTMin())
+    {
+        DoSomething();
+    }
+// CHECK:  OpRayQueryGetWorldRayDirectionKHR %v3float [[rayquery]]
+    float3 o = q.WorldRayDirection();
+// CHECK:  OpRayQueryGetWorldRayOriginKHR %v3float [[rayquery]]
+    float3 d = q.WorldRayOrigin();
+    if(o.x == d.z)
+    {
+        DoSomething();
+    }
+}