浏览代码

[spirv] Support CheckAccessFullyMapped intrinsic. (#897)

Ehsan 7 年之前
父节点
当前提交
679b7c80c7

+ 1 - 2
docs/SPIR-V.rst

@@ -1516,6 +1516,7 @@ The following intrinsic HLSL functions have direct SPIR-V opcodes for them:
 ``isInf``                            ``OpIsInf``
 ``reversebits``                      ``OpBitReverse``
 ``transpose``                        ``OpTranspose``
+``CheckAccessFullyMapped``           ``OpImageSparseTexelsResident``
 ==================================== =================================
 
 Using GLSL extended instructions
@@ -2279,8 +2280,6 @@ either because of no Vulkan equivalents at the moment, or because of deprecation
   emit a warning and ignore it.
 * ``abort()`` intrinsic function: no Vulkan equivalent. The compiler will emit
   an error.
-* ``CheckAccessFullyMapped()`` intrinsic function: no Vulkan equivalent.
-  The compiler will emit an error.
 * ``GetRenderTargetSampleCount()`` intrinsic function: no Vulkan equivalent.
   (Its GLSL counterpart is ``gl_NumSamples``, which is not available in GLSL for
   Vulkan.) The compiler will emit an error.

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

@@ -863,7 +863,7 @@ public:
   opImageSample(uint32_t result_type, uint32_t result_id,
                 uint32_t sampled_image, uint32_t coordinate, uint32_t dref,
                 llvm::Optional<spv::ImageOperandsMask> image_operands,
-                bool isExplicit, bool isSparse);
+                bool is_explicit, bool is_sparse);
 
   // Methods for supplying additional parameters.
   InstBuilder &fPFastMathMode(spv::FPFastMathModeMask);

+ 5 - 1
tools/clang/include/clang/SPIRV/ModuleBuilder.h

@@ -172,7 +172,7 @@ public:
   /// be generated.
   ///
   /// If bias, lod, grad, or minLod is given a non-zero value, an additional
-  /// image operands, Bias, Lod, Grad, or minLod will be attached to the current
+  /// image operands, Bias, Lod, Grad, or MinLod will be attached to the current
   /// instruction, respectively. Panics if both lod and minLod are non-zero.
   ///
   /// If residencyCodeId is not zero, the sparse version of the instructions
@@ -216,6 +216,10 @@ public:
                              uint32_t varOffset, uint32_t constOffsets,
                              uint32_t sample, uint32_t residencyCodeId);
 
+  /// \brief Creates an OpImageSparseTexelsResident SPIR-V instruction for the
+  /// given Resident Code and returns the <result-id> of the instruction.
+  uint32_t createImageSparseTexelsResident(uint32_t resident_code);
+
   /// \brief Creates a select operation with the given values for true and false
   /// cases and returns the <result-id> for the result.
   uint32_t createSelect(uint32_t resultType, uint32_t condition,

+ 11 - 11
tools/clang/lib/SPIRV/InstBuilderManual.cpp

@@ -83,19 +83,19 @@ InstBuilder &InstBuilder::opConstant(uint32_t resultType, uint32_t resultId,
 InstBuilder &InstBuilder::opImageSample(
     uint32_t result_type, uint32_t result_id, uint32_t sampled_image,
     uint32_t coordinate, uint32_t dref,
-    llvm::Optional<spv::ImageOperandsMask> image_operands, bool isExplicit,
-    bool isSparse) {
+    llvm::Optional<spv::ImageOperandsMask> image_operands, bool is_explicit,
+    bool is_sparse) {
   spv::Op op = spv::Op::Max;
   if (dref) {
-    op = isExplicit ? (isSparse ? spv::Op::OpImageSparseSampleDrefExplicitLod
-                                : spv::Op::OpImageSampleDrefExplicitLod)
-                    : (isSparse ? spv::Op::OpImageSparseSampleDrefImplicitLod
-                                : spv::Op::OpImageSampleDrefImplicitLod);
+    op = is_explicit ? (is_sparse ? spv::Op::OpImageSparseSampleDrefExplicitLod
+                                  : spv::Op::OpImageSampleDrefExplicitLod)
+                     : (is_sparse ? spv::Op::OpImageSparseSampleDrefImplicitLod
+                                  : spv::Op::OpImageSampleDrefImplicitLod);
   } else {
-    op = isExplicit ? (isSparse ? spv::Op::OpImageSparseSampleExplicitLod
-                                : spv::Op::OpImageSampleExplicitLod)
-                    : (isSparse ? spv::Op::OpImageSparseSampleImplicitLod
-                                : spv::Op::OpImageSampleImplicitLod);
+    op = is_explicit ? (is_sparse ? spv::Op::OpImageSparseSampleExplicitLod
+                                  : spv::Op::OpImageSampleExplicitLod)
+                     : (is_sparse ? spv::Op::OpImageSparseSampleImplicitLod
+                                  : spv::Op::OpImageSampleImplicitLod);
   }
 
   TheInst.emplace_back(static_cast<uint32_t>(op));
@@ -103,7 +103,7 @@ InstBuilder &InstBuilder::opImageSample(
   TheInst.emplace_back(result_id);
   TheInst.emplace_back(sampled_image);
   TheInst.emplace_back(coordinate);
-  if(dref)
+  if (dref)
     TheInst.emplace_back(dref);
   if (image_operands.hasValue()) {
     const auto &val = image_operands.getValue();

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

@@ -339,6 +339,17 @@ spv::ImageOperandsMask ModuleBuilder::composeImageOperandsMask(
   return mask;
 }
 
+uint32_t
+ModuleBuilder::createImageSparseTexelsResident(uint32_t resident_code) {
+  assert(insertPoint && "null insert point");
+  // Result type must be a boolean
+  const uint32_t result_type = getBoolType();
+  const uint32_t id = theContext.takeNextId();
+  instBuilder.opImageSparseTexelsResident(result_type, id, resident_code).x();
+  insertPoint->appendInstruction(std::move(constructSite));
+  return id;
+}
+
 uint32_t ModuleBuilder::createImageTexelPointer(uint32_t resultType,
                                                 uint32_t imageId,
                                                 uint32_t coordinate,

+ 4 - 1
tools/clang/lib/SPIRV/SPIRVEmitter.cpp

@@ -4625,6 +4625,10 @@ SpirvEvalInfo SPIRVEmitter::processIntrinsicCallExpr(const CallExpr *callExpr) {
                                            /*groupSync*/ true,
                                            /*isAllBarrier*/ true);
     break;
+  case hlsl::IntrinsicOp::IOP_CheckAccessFullyMapped:
+    retVal =
+        theBuilder.createImageSparseTexelsResident(doExpr(callExpr->getArg(0)));
+    break;
   case hlsl::IntrinsicOp::IOP_mul:
     retVal = processIntrinsicMul(callExpr);
     break;
@@ -4695,7 +4699,6 @@ SpirvEvalInfo SPIRVEmitter::processIntrinsicCallExpr(const CallExpr *callExpr) {
     retVal = processIntrinsicF32ToF16(callExpr);
     break;
   case hlsl::IntrinsicOp::IOP_abort:
-  case hlsl::IntrinsicOp::IOP_CheckAccessFullyMapped:
   case hlsl::IntrinsicOp::IOP_GetRenderTargetSampleCount:
   case hlsl::IntrinsicOp::IOP_GetRenderTargetSamplePosition: {
     emitError("no equivalent for %0 intrinsic function in Vulkan",

+ 18 - 5
tools/clang/test/CodeGenSPIRV/intrinsics.check-access-fully-mapped.hlsl

@@ -1,8 +1,21 @@
 // Run: %dxc -T ps_6_0 -E main
 
-void main() {
-  uint status;
-  bool fullyMapped = CheckAccessFullyMapped(status);
-}
+SamplerState      gSampler  : register(s5);
+Texture2D<float4> t         : register(t1);
+
+// CHECK: OpCapability SparseResidency
+
+// CHECK: %SparseResidencyStruct = OpTypeStruct %uint %v4float
 
-// CHECK: error: no equivalent for CheckAccessFullyMapped intrinsic function in Vulkan
+float4 main(int2 offset: A) : SV_Target {
+    uint status;
+    float clamp;
+    float4 val = t.Sample(gSampler, float2(0.1, 0.2), offset, clamp, status);
+    
+// CHECK: [[residency_code:%\d+]] = OpLoad %uint %status
+// CHECK:        [[success:%\d+]] = OpImageSparseTexelsResident %bool [[residency_code]]
+// CHECK:                           OpStore %success [[success]]
+    bool success = CheckAccessFullyMapped(status);
+
+    return 1.0;
+}

+ 1 - 1
tools/clang/unittests/SPIRV/CodeGenSPIRVTest.cpp

@@ -831,7 +831,7 @@ TEST_F(FileTest, IntrinsicsAbort) {
   runFileTest("intrinsics.abort.hlsl", Expect::Failure);
 }
 TEST_F(FileTest, IntrinsicsCheckAccessFullyMapped) {
-  runFileTest("intrinsics.check-access-fully-mapped.hlsl", Expect::Failure);
+  runFileTest("intrinsics.check-access-fully-mapped.hlsl");
 }
 TEST_F(FileTest, IntrinsicsGetRenderTargetSampleCount) {
   runFileTest("intrinsics.get-render-target-sample-count.hlsl",