2
0
Эх сурвалжийг харах

[spirv] CalculateLevelOfDetail for Texture types. (#653)

Ehsan 8 жил өмнө
parent
commit
52c27ffbbd

+ 54 - 0
docs/SPIR-V.rst

@@ -1262,6 +1262,12 @@ Since Texture1D is represented as ``OpTypeImage``, the ``OpImageQuerySizeLod`` i
 is used for translation. If a ``MipLevel`` argument is passed to ``GetDimensions``, it will
 be used as the ``Lod`` parameter of the query instruction. Otherwise, ``Lod`` of ``0`` be used.
 
+``.CalculateLevelOfDetail()``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Since Texture1D is represented as ``OpTypeImage``, the ``OpImageQueryLod`` instruction is used
+for translation. An ``OpSampledImage`` is created based on the SamplerState passed to the function.
+The resulting sampled image and the coordinate passed to the function are used to invoke ``OpImageQueryLod``.
+The result of ``OpImageQueryLod`` is a float2. The first element contains the mipmap array layer.
 
 ``Texture1DArray``
 --------------------------
@@ -1272,6 +1278,13 @@ Since Texture1DArray is represented as ``OpTypeImage``, the ``OpImageQuerySizeLo
 is used for translation. If a ``MipLevel`` argument is present, it will be used as the
 ``Lod`` parameter of the query instruction. Otherwise, ``Lod`` of ``0`` be used.
 
+``.CalculateLevelOfDetail()``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Since Texture1DArray is represented as ``OpTypeImage``, the ``OpImageQueryLod`` instruction is used
+for translation. An ``OpSampledImage`` is created based on the SamplerState passed to the function.
+The resulting sampled image and the coordinate passed to the function are used to invoke ``OpImageQueryLod``.
+The result of ``OpImageQueryLod`` is a float2. The first element contains the mipmap array layer.
+
 ``Texture2D``
 --------------------------
 
@@ -1281,6 +1294,13 @@ Since Texture2D is represented as ``OpTypeImage``, the ``OpImageQuerySizeLod`` i
 is used for translation. If a ``MipLevel`` argument is present, it will be used as the
 ``Lod`` parameter of the query instruction. Otherwise, ``Lod`` of ``0`` be used.
 
+``.CalculateLevelOfDetail()``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Since Texture2D is represented as ``OpTypeImage``, the ``OpImageQueryLod`` instruction is used
+for translation. An ``OpSampledImage`` is created based on the SamplerState passed to the function.
+The resulting sampled image and the coordinate passed to the function are used to invoke ``OpImageQueryLod``.
+The result of ``OpImageQueryLod`` is a float2. The first element contains the mipmap array layer.
+
 ``Texture2DArray``
 --------------------------
 
@@ -1290,6 +1310,13 @@ Since Texture2DArray is represented as ``OpTypeImage``, the ``OpImageQuerySizeLo
 is used for translation. If a ``MipLevel`` argument is present, it will be used as the
 ``Lod`` parameter of the query instruction. Otherwise, ``Lod`` of ``0`` be used.
 
+``.CalculateLevelOfDetail()``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Since Texture2DArray is represented as ``OpTypeImage``, the ``OpImageQueryLod`` instruction is used
+for translation. An ``OpSampledImage`` is created based on the SamplerState passed to the function.
+The resulting sampled image and the coordinate passed to the function are used to invoke ``OpImageQueryLod``.
+The result of ``OpImageQueryLod`` is a float2. The first element contains the mipmap array layer.
+
 ``Texture3D``
 --------------------------
 
@@ -1299,6 +1326,13 @@ Since Texture3D is represented as ``OpTypeImage``, the ``OpImageQuerySizeLod`` i
 is used for translation. If a ``MipLevel`` argument is present, it will be used as the
 ``Lod`` parameter of the query instruction. Otherwise, ``Lod`` of ``0`` be used.
 
+``.CalculateLevelOfDetail()``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Since Texture3D is represented as ``OpTypeImage``, the ``OpImageQueryLod`` instruction is used
+for translation. An ``OpSampledImage`` is created based on the SamplerState passed to the function.
+The resulting sampled image and the coordinate passed to the function are used to invoke ``OpImageQueryLod``.
+The result of ``OpImageQueryLod`` is a float2. The first element contains the mipmap array layer.
+
 ``Texture2DMS``
 --------------------------
 
@@ -1315,6 +1349,26 @@ is used to get the width and the height. Furthermore, ``OpImageQuerySamples`` is
 Since Texture2DMS is represented as ``OpTypeImage`` with ``MS`` of ``1``, the ``OpImageQuerySize`` instruction
 is used to get the width, the height, and the elements. Furthermore, ``OpImageQuerySamples`` is used to get the numSamples.
 
+``TextureCube``
+--------------------------
+
+``.CalculateLevelOfDetail()``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Since TextureCube is represented as ``OpTypeImage``, the ``OpImageQueryLod`` instruction is used
+for translation. An ``OpSampledImage`` is created based on the SamplerState passed to the function.
+The resulting sampled image and the coordinate passed to the function are used to invoke ``OpImageQueryLod``.
+The result of ``OpImageQueryLod`` is a float2. The first element contains the mipmap array layer.
+
+``TextureCubeArray``
+--------------------------
+
+``.CalculateLevelOfDetail()``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Since TextureCubeArray is represented as ``OpTypeImage``, the ``OpImageQueryLod`` instruction is used
+for translation. An ``OpSampledImage`` is created based on the SamplerState passed to the function.
+The resulting sampled image and the coordinate passed to the function are used to invoke ``OpImageQueryLod``.
+The result of ``OpImageQueryLod`` is a float2. The first element contains the mipmap array layer.
+
 ``RWTexture1D``
 --------------------------
 

+ 32 - 0
tools/clang/lib/SPIRV/SPIRVEmitter.cpp

@@ -1538,6 +1538,35 @@ SPIRVEmitter::processBufferTextureGetDimensions(const CXXMemberCallExpr *expr) {
   return 0;
 }
 
+uint32_t
+SPIRVEmitter::processTextureLevelOfDetail(const CXXMemberCallExpr *expr) {
+  // Possible signatures are as follows:
+  // Texture1D(Array).CalculateLevelOfDetail(SamplerState S, float x);
+  // Texture2D(Array).CalculateLevelOfDetail(SamplerState S, float2 xy);
+  // TextureCube(Array).CalculateLevelOfDetail(SamplerState S, float3 xyz);
+  // Texture3D.CalculateLevelOfDetail(SamplerState S, float3 xyz);
+  // Return type is always a single float (LOD).
+  assert(expr->getNumArgs() == 2u);
+  theBuilder.requireCapability(spv::Capability::ImageQuery);
+  const auto *object = expr->getImplicitObjectArgument();
+  const uint32_t objectId = loadIfGLValue(object);
+  const uint32_t samplerState = doExpr(expr->getArg(0));
+  const uint32_t coordinate = doExpr(expr->getArg(1));
+  const uint32_t sampledImageType = theBuilder.getSampledImageType(
+      typeTranslator.translateType(object->getType()));
+  const uint32_t sampledImage = theBuilder.createBinaryOp(
+      spv::Op::OpSampledImage, sampledImageType, objectId, samplerState);
+
+  // The result type of OpImageQueryLod must be a float2.
+  const uint32_t queryResultType =
+      theBuilder.getVecType(theBuilder.getFloat32Type(), 2u);
+  const uint32_t query = theBuilder.createBinaryOp(
+      spv::Op::OpImageQueryLod, queryResultType, sampledImage, coordinate);
+  // The first component of the float2 contains the mipmap array layer.
+  return theBuilder.createCompositeExtract(theBuilder.getFloat32Type(), query,
+                                           {0});
+}
+
 uint32_t SPIRVEmitter::processBufferTextureLoad(const Expr *object,
                                                 const uint32_t locationId,
                                                 uint32_t constOffset,
@@ -2003,6 +2032,9 @@ uint32_t SPIRVEmitter::processIntrinsicMemberCall(const CXXMemberCallExpr *expr,
       return 0;
     }
   }
+  case IntrinsicOp::MOP_CalculateLevelOfDetail: {
+    return processTextureLevelOfDetail(expr);
+  }
   }
   emitError("HLSL intrinsic member call unimplemented: %0")
       << callee->getName();

+ 4 - 0
tools/clang/lib/SPIRV/SPIRVEmitter.h

@@ -483,6 +483,10 @@ private:
   /// the loaded value for .Consume; returns zero for .Append().
   uint32_t processACSBufferAppendConsume(const CXXMemberCallExpr *expr);
 
+  /// \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);
+
 private:
   /// \brief Queries the given (RW)Buffer/(RW)Texture image in the given expr
   /// for the requested information. Based on the dimension of the image, the

+ 83 - 0
tools/clang/test/CodeGenSPIRV/texture.calculate-lod.hlsl

@@ -0,0 +1,83 @@
+// Run: %dxc -T ps_6_0 -E main
+
+// CHECK: OpCapability ImageQuery
+
+SamplerState ss : register(s2);
+
+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() {
+  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]] 0
+  float lod1 = t1.CalculateLevelOfDetail(ss, x);
+
+//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]] 0
+  float lod2 = t2.CalculateLevelOfDetail(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]] 0
+  float lod3 = t3.CalculateLevelOfDetail(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]] 0
+  float lod4 = t4.CalculateLevelOfDetail(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]] 0
+  float lod5 = t5.CalculateLevelOfDetail(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]] 0
+  float lod6 = t6.CalculateLevelOfDetail(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]] 0
+  float lod7 = t7.CalculateLevelOfDetail(ss, xyz);
+}

+ 3 - 0
tools/clang/unittests/SPIRV/CodeGenSPIRVTest.cpp

@@ -371,6 +371,9 @@ TEST_F(FileTest, TextureArrayLoad) { runFileTest("texture.array.load.hlsl"); }
 TEST_F(FileTest, TextureGetDimensions) {
   runFileTest("texture.get-dimensions.hlsl");
 }
+TEST_F(FileTest, TextureCalculateLevelOfDetail) {
+  runFileTest("texture.calculate-lod.hlsl");
+}
 TEST_F(FileTest, TextureGather) { runFileTest("texture.gather.hlsl"); }
 TEST_F(FileTest, TextureArrayGather) {
   runFileTest("texture.array.gather.hlsl");