Browse Source

[spirv] Handle CalculateLevelOfDetailUnclamped. (#1400)

Ehsan 7 years ago
parent
commit
18545516b0

+ 3 - 6
docs/SPIR-V.rst

@@ -2280,8 +2280,8 @@ parameter is attached to the instruction as the parameter to the ``Lod`` SPIR-V
 image operands. The ``position`` parameter are used as the coordinate to the
 image operands. The ``position`` parameter are used as the coordinate to the
 instruction directly.
 instruction directly.
 
 
-``.CalculateLevelOfDetail()``
-+++++++++++++++++++++++++++++
+``.CalculateLevelOfDetail()`` and ``.CalculateLevelOfDetailUnclamped()``
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
 
 Not available to ``Texture2DMS`` and ``Texture2DMSArray``.
 Not available to ``Texture2DMS`` and ``Texture2DMSArray``.
 
 
@@ -2290,7 +2290,7 @@ instruction is used for translation. An ``OpSampledImage`` is created based on
 the ``SamplerState`` passed to the function. The resulting sampled image and
 the ``SamplerState`` passed to the function. The resulting sampled image and
 the coordinate passed to the function are used to invoke ``OpImageQueryLod``.
 the coordinate passed to the function are used to invoke ``OpImageQueryLod``.
 The result of ``OpImageQueryLod`` is a ``float2``. The first element contains
 The result of ``OpImageQueryLod`` is a ``float2``. The first element contains
-the mipmap array layer.
+the mipmap array layer. The second element contains the unclamped level of detail.
 
 
 ``Texture1D``
 ``Texture1D``
 ~~~~~~~~~~~~~
 ~~~~~~~~~~~~~
@@ -2753,9 +2753,6 @@ either because of no Vulkan equivalents at the moment, or because of deprecation
 * ``.GatherCmpGreen()``, ``.GatherCmpBlue()``, ``.GatherCmpAlpha()`` intrinsic
 * ``.GatherCmpGreen()``, ``.GatherCmpBlue()``, ``.GatherCmpAlpha()`` intrinsic
   method: no Vulkan equivalent. (SPIR-V ``OpImageDrefGather`` instruction does
   method: no Vulkan equivalent. (SPIR-V ``OpImageDrefGather`` instruction does
   not take component as input.) The compiler will emit an error.
   not take component as input.) The compiler will emit an error.
-* ``.CalculateLevelOfDetailUnclamped()`` intrinsic method: no Vulkan equivalent.
-  (SPIR-V ``OpImageQueryLod`` returns the clamped LOD in Vulkan.) The compiler
-  will emit an error.
 * Since ``StructuredBuffer``, ``RWStructuredBuffer``, ``ByteAddressBuffer``, and
 * Since ``StructuredBuffer``, ``RWStructuredBuffer``, ``ByteAddressBuffer``, and
   ``RWByteAddressBuffer`` are not represented as image types in SPIR-V, using the
   ``RWByteAddressBuffer`` are not represented as image types in SPIR-V, using the
   output unsigned integer ``status`` argument in their ``Load*`` methods is not
   output unsigned integer ``status`` argument in their ``Load*`` methods is not

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

@@ -2932,7 +2932,8 @@ SPIRVEmitter::processBufferTextureGetDimensions(const CXXMemberCallExpr *expr) {
 }
 }
 
 
 uint32_t
 uint32_t
-SPIRVEmitter::processTextureLevelOfDetail(const CXXMemberCallExpr *expr) {
+SPIRVEmitter::processTextureLevelOfDetail(const CXXMemberCallExpr *expr,
+                                          bool unclamped) {
   // Possible signatures are as follows:
   // Possible signatures are as follows:
   // Texture1D(Array).CalculateLevelOfDetail(SamplerState S, float x);
   // Texture1D(Array).CalculateLevelOfDetail(SamplerState S, float x);
   // Texture2D(Array).CalculateLevelOfDetail(SamplerState S, float2 xy);
   // Texture2D(Array).CalculateLevelOfDetail(SamplerState S, float2 xy);
@@ -2960,9 +2961,11 @@ SPIRVEmitter::processTextureLevelOfDetail(const CXXMemberCallExpr *expr) {
       theBuilder.getVecType(theBuilder.getFloat32Type(), 2u);
       theBuilder.getVecType(theBuilder.getFloat32Type(), 2u);
   const uint32_t query = theBuilder.createBinaryOp(
   const uint32_t query = theBuilder.createBinaryOp(
       spv::Op::OpImageQueryLod, queryResultType, sampledImage, coordinate);
       spv::Op::OpImageQueryLod, queryResultType, sampledImage, coordinate);
+
   // The first component of the float2 contains the mipmap array layer.
   // The first component of the float2 contains the mipmap array layer.
+  // The second component of the float2 represents the unclamped lod.
   return theBuilder.createCompositeExtract(theBuilder.getFloat32Type(), query,
   return theBuilder.createCompositeExtract(theBuilder.getFloat32Type(), query,
-                                           {0});
+                                           unclamped ? 1 : 0);
 }
 }
 
 
 uint32_t SPIRVEmitter::processTextureGatherRGBACmpRGBA(
 uint32_t SPIRVEmitter::processTextureGatherRGBACmpRGBA(
@@ -3842,7 +3845,9 @@ SPIRVEmitter::processIntrinsicMemberCall(const CXXMemberCallExpr *expr,
     retVal = processGetDimensions(expr);
     retVal = processGetDimensions(expr);
     break;
     break;
   case IntrinsicOp::MOP_CalculateLevelOfDetail:
   case IntrinsicOp::MOP_CalculateLevelOfDetail:
-    retVal = processTextureLevelOfDetail(expr);
+    retVal = processTextureLevelOfDetail(expr, /* unclamped */ false);
+  case IntrinsicOp::MOP_CalculateLevelOfDetailUnclamped:
+    retVal = processTextureLevelOfDetail(expr, /* unclamped */ true);
     break;
     break;
   case IntrinsicOp::MOP_IncrementCounter:
   case IntrinsicOp::MOP_IncrementCounter:
     retVal = theBuilder.createUnaryOp(
     retVal = theBuilder.createUnaryOp(
@@ -3887,7 +3892,6 @@ SPIRVEmitter::processIntrinsicMemberCall(const CXXMemberCallExpr *expr,
   case IntrinsicOp::MOP_GatherCmpGreen:
   case IntrinsicOp::MOP_GatherCmpGreen:
   case IntrinsicOp::MOP_GatherCmpBlue:
   case IntrinsicOp::MOP_GatherCmpBlue:
   case IntrinsicOp::MOP_GatherCmpAlpha:
   case IntrinsicOp::MOP_GatherCmpAlpha:
-  case IntrinsicOp::MOP_CalculateLevelOfDetailUnclamped:
     emitError("no equivalent for %0 intrinsic method in Vulkan",
     emitError("no equivalent for %0 intrinsic method in Vulkan",
               expr->getCallee()->getExprLoc())
               expr->getCallee()->getExprLoc())
         << expr->getMethodDecl()->getName();
         << expr->getMethodDecl()->getName();

+ 5 - 2
tools/clang/lib/SPIRV/SPIRVEmitter.h

@@ -755,8 +755,11 @@ private:
   uint32_t processTextureGatherCmp(const CXXMemberCallExpr *expr);
   uint32_t processTextureGatherCmp(const CXXMemberCallExpr *expr);
 
 
   /// \brief Returns the calculated level-of-detail (a single float value) for
   /// \brief Returns the calculated level-of-detail (a single float value) for
-  /// the given texture. Handles intrinsic HLSL CalculateLevelOfDetail function.
-  uint32_t processTextureLevelOfDetail(const CXXMemberCallExpr *expr);
+  /// the given texture. Handles intrinsic HLSL CalculateLevelOfDetail or
+  /// CalculateLevelOfDetailUnclamped function depending on the given unclamped
+  /// parameter.
+  uint32_t processTextureLevelOfDetail(const CXXMemberCallExpr *expr,
+                                       bool unclamped);
 
 
   /// \brief Processes the .GetDimensions() call on supported objects.
   /// \brief Processes the .GetDimensions() call on supported objects.
   uint32_t processGetDimensions(const CXXMemberCallExpr *);
   uint32_t processGetDimensions(const CXXMemberCallExpr *);

+ 72 - 2
tools/clang/test/CodeGenSPIRV/texture.calculate-lod-unclamped.hlsl

@@ -1,13 +1,83 @@
 // Run: %dxc -T ps_6_0 -E main
 // Run: %dxc -T ps_6_0 -E main
 
 
+// CHECK: OpCapability ImageQuery
+
 SamplerState ss : register(s2);
 SamplerState ss : register(s2);
 
 
 Texture1D        <float>  t1;
 Texture1D        <float>  t1;
+Texture1DArray   <float4> t2;
+Texture2D        <int2>   t3;
+Texture2DArray   <int3>   t4;
+Texture3D        <uint3>  t5;
+TextureCube      <int>    t6;
+TextureCubeArray <int>    t7;
+
+// CHECK:   %type_sampled_image = OpTypeSampledImage %type_1d_image
+// CHECK: %type_sampled_image_0 = OpTypeSampledImage %type_1d_image_array
+// CHECK: %type_sampled_image_1 = OpTypeSampledImage %type_2d_image
+// CHECK: %type_sampled_image_2 = OpTypeSampledImage %type_2d_image_array
+// CHECK: %type_sampled_image_3 = OpTypeSampledImage %type_3d_image
+// CHECK: %type_sampled_image_4 = OpTypeSampledImage %type_cube_image
+// CHECK: %type_sampled_image_5 = OpTypeSampledImage %type_cube_image_array
 
 
 void main() {
 void main() {
   float x = 0.5;
   float x = 0.5;
+  float2 xy = float2(0.5, 0.5);
+  float3 xyz = float3(0.5, 0.5, 0.5);
 
 
+//CHECK:          [[t1:%\d+]] = OpLoad %type_1d_image %t1
+//CHECK-NEXT:    [[ss1:%\d+]] = OpLoad %type_sampler %ss
+//CHECK-NEXT:     [[x1:%\d+]] = OpLoad %float %x
+//CHECK-NEXT:    [[si1:%\d+]] = OpSampledImage %type_sampled_image [[t1]] [[ss1]]
+//CHECK-NEXT: [[query1:%\d+]] = OpImageQueryLod %v2float [[si1]] [[x1]]
+//CHECK-NEXT:        {{%\d+}} = OpCompositeExtract %float [[query1]] 1
   float lod1 = t1.CalculateLevelOfDetailUnclamped(ss, x);
   float lod1 = t1.CalculateLevelOfDetailUnclamped(ss, x);
-}
 
 
-// CHECK: :10:19: error: no equivalent for CalculateLevelOfDetailUnclamped intrinsic method in Vulkan
+//CHECK:          [[t2:%\d+]] = OpLoad %type_1d_image_array %t2
+//CHECK-NEXT:    [[ss2:%\d+]] = OpLoad %type_sampler %ss
+//CHECK-NEXT:     [[x2:%\d+]] = OpLoad %float %x
+//CHECK-NEXT:    [[si2:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2]] [[ss2]]
+//CHECK-NEXT: [[query2:%\d+]] = OpImageQueryLod %v2float [[si2]] [[x2]]
+//CHECK-NEXT:        {{%\d+}} = OpCompositeExtract %float [[query2]] 1
+  float lod2 = t2.CalculateLevelOfDetailUnclamped(ss, x);
+
+//CHECK:          [[t3:%\d+]] = OpLoad %type_2d_image %t3
+//CHECK-NEXT:    [[ss3:%\d+]] = OpLoad %type_sampler %ss
+//CHECK-NEXT:    [[xy1:%\d+]] = OpLoad %v2float %xy
+//CHECK-NEXT:    [[si3:%\d+]] = OpSampledImage %type_sampled_image_1 [[t3]] [[ss3]]
+//CHECK-NEXT: [[query3:%\d+]] = OpImageQueryLod %v2float [[si3]] [[xy1]]
+//CHECK-NEXT:        {{%\d+}} = OpCompositeExtract %float [[query3]] 1
+  float lod3 = t3.CalculateLevelOfDetailUnclamped(ss, xy);
+
+//CHECK:          [[t4:%\d+]] = OpLoad %type_2d_image_array %t4
+//CHECK-NEXT:    [[ss4:%\d+]] = OpLoad %type_sampler %ss
+//CHECK-NEXT:    [[xy2:%\d+]] = OpLoad %v2float %xy
+//CHECK-NEXT:    [[si4:%\d+]] = OpSampledImage %type_sampled_image_2 [[t4]] [[ss4]]
+//CHECK-NEXT: [[query4:%\d+]] = OpImageQueryLod %v2float [[si4]] [[xy2]]
+//CHECK-NEXT:        {{%\d+}} = OpCompositeExtract %float [[query4]] 1
+  float lod4 = t4.CalculateLevelOfDetailUnclamped(ss, xy);
+
+//CHECK:          [[t5:%\d+]] = OpLoad %type_3d_image %t5
+//CHECK-NEXT:    [[ss5:%\d+]] = OpLoad %type_sampler %ss
+//CHECK-NEXT:   [[xyz1:%\d+]] = OpLoad %v3float %xyz
+//CHECK-NEXT:    [[si5:%\d+]] = OpSampledImage %type_sampled_image_3 [[t5]] [[ss5]]
+//CHECK-NEXT: [[query5:%\d+]] = OpImageQueryLod %v2float [[si5]] [[xyz1]]
+//CHECK-NEXT:        {{%\d+}} = OpCompositeExtract %float [[query5]] 1
+  float lod5 = t5.CalculateLevelOfDetailUnclamped(ss, xyz);
+
+//CHECK:          [[t6:%\d+]] = OpLoad %type_cube_image %t6
+//CHECK-NEXT:    [[ss6:%\d+]] = OpLoad %type_sampler %ss
+//CHECK-NEXT:   [[xyz2:%\d+]] = OpLoad %v3float %xyz
+//CHECK-NEXT:    [[si6:%\d+]] = OpSampledImage %type_sampled_image_4 [[t6]] [[ss6]]
+//CHECK-NEXT: [[query6:%\d+]] = OpImageQueryLod %v2float [[si6]] [[xyz2]]
+//CHECK-NEXT:        {{%\d+}} = OpCompositeExtract %float [[query6]] 1
+  float lod6 = t6.CalculateLevelOfDetailUnclamped(ss, xyz);
+
+//CHECK:          [[t7:%\d+]] = OpLoad %type_cube_image_array %t7
+//CHECK-NEXT:    [[ss7:%\d+]] = OpLoad %type_sampler %ss
+//CHECK-NEXT:   [[xyz3:%\d+]] = OpLoad %v3float %xyz
+//CHECK-NEXT:    [[si7:%\d+]] = OpSampledImage %type_sampled_image_5 [[t7]] [[ss7]]
+//CHECK-NEXT: [[query7:%\d+]] = OpImageQueryLod %v2float [[si7]] [[xyz3]]
+//CHECK-NEXT:        {{%\d+}} = OpCompositeExtract %float [[query7]] 1
+  float lod7 = t7.CalculateLevelOfDetailUnclamped(ss, xyz);
+}

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

@@ -711,7 +711,7 @@ TEST_F(FileTest, TextureCalculateLevelOfDetail) {
   runFileTest("texture.calculate-lod.hlsl");
   runFileTest("texture.calculate-lod.hlsl");
 }
 }
 TEST_F(FileTest, TextureCalculateLevelOfDetailUnclamped) {
 TEST_F(FileTest, TextureCalculateLevelOfDetailUnclamped) {
-  runFileTest("texture.calculate-lod-unclamped.hlsl", Expect::Failure);
+  runFileTest("texture.calculate-lod-unclamped.hlsl");
 }
 }
 TEST_F(FileTest, TextureGather) { runFileTest("texture.gather.hlsl"); }
 TEST_F(FileTest, TextureGather) { runFileTest("texture.gather.hlsl"); }
 TEST_F(FileTest, TextureArrayGather) {
 TEST_F(FileTest, TextureArrayGather) {