Bladeren bron

[spirv] Allow signed integer args in GetDimensions (#1249)

Ehsan 7 jaren geleden
bovenliggende
commit
9c32ea432c
2 gewijzigde bestanden met toevoegingen van 42 en 15 verwijderingen
  1. 14 15
      tools/clang/lib/SPIRV/SPIRVEmitter.cpp
  2. 28 0
      tools/clang/test/CodeGenSPIRV/texture.get-dimensions.hlsl

+ 14 - 15
tools/clang/lib/SPIRV/SPIRVEmitter.cpp

@@ -2760,16 +2760,10 @@ SPIRVEmitter::processBufferTextureGetDimensions(const CXXMemberCallExpr *expr) {
   // The HLSL methods, however, have overloaded functions which have float
   // output arguments. Since the AST naturally won't have casting AST nodes for
   // such cases, we'll have to perform the cast ourselves.
-  const auto storeToOutputArg = [this](const Expr *outputArg,
-                                       uint32_t toStoreId) {
-    const auto outputArgType = outputArg->getType();
-    // Perform cast to float if necessary.
-    if (isFloatOrVecMatOfFloatType(outputArgType)) {
-      toStoreId = theBuilder.createUnaryOp(
-          spv::Op::OpConvertUToF, typeTranslator.translateType(outputArgType),
-          toStoreId);
-    }
-    theBuilder.createStore(doExpr(outputArg), toStoreId);
+  const auto storeToOutputArg = [this](const Expr *outputArg, uint32_t id,
+                                       QualType type) {
+    id = castToType(id, type, outputArg->getType(), outputArg->getExprLoc());
+    theBuilder.createStore(doExpr(outputArg), id);
   };
 
   if ((typeName == "Texture1D" && numArgs > 1) ||
@@ -2796,8 +2790,11 @@ SPIRVEmitter::processBufferTextureGetDimensions(const CXXMemberCallExpr *expr) {
     querySize -= 1;
 
   const uint32_t uintId = theBuilder.getUint32Type();
-  const uint32_t resultTypeId =
-      querySize == 1 ? uintId : theBuilder.getVecType(uintId, querySize);
+  const QualType resultQualType =
+      querySize == 1
+          ? astContext.UnsignedIntTy
+          : astContext.getExtVectorType(astContext.UnsignedIntTy, querySize);
+  const uint32_t resultTypeId = typeTranslator.translateType(resultQualType);
 
   // Only Texture types use ImageQuerySizeLod.
   // TextureMS, RWTexture, Buffers, RWBuffers use ImageQuerySize.
@@ -2820,7 +2817,7 @@ SPIRVEmitter::processBufferTextureGetDimensions(const CXXMemberCallExpr *expr) {
 
   if (querySize == 1) {
     const uint32_t argIndex = mipLevel ? 1 : 0;
-    storeToOutputArg(expr->getArg(argIndex), query);
+    storeToOutputArg(expr->getArg(argIndex), query, resultQualType);
   } else {
     for (uint32_t i = 0; i < querySize; ++i) {
       const uint32_t component =
@@ -2828,7 +2825,8 @@ SPIRVEmitter::processBufferTextureGetDimensions(const CXXMemberCallExpr *expr) {
       // If the first arg is the mipmap level, we must write the results
       // starting from Arg(i+1), not Arg(i).
       const uint32_t argIndex = mipLevel ? i + 1 : i;
-      storeToOutputArg(expr->getArg(argIndex), component);
+      storeToOutputArg(expr->getArg(argIndex), component,
+                       astContext.UnsignedIntTy);
     }
   }
 
@@ -2838,7 +2836,8 @@ SPIRVEmitter::processBufferTextureGetDimensions(const CXXMemberCallExpr *expr) {
         numLevels ? spv::Op::OpImageQueryLevels : spv::Op::OpImageQuerySamples;
     const uint32_t numLevelsSamplesQuery =
         theBuilder.createUnaryOp(opcode, uintId, objectId);
-    storeToOutputArg(numLevelsSamplesArg, numLevelsSamplesQuery);
+    storeToOutputArg(numLevelsSamplesArg, numLevelsSamplesQuery,
+                     astContext.UnsignedIntTy);
   }
 
   return 0;

+ 28 - 0
tools/clang/test/CodeGenSPIRV/texture.get-dimensions.hlsl

@@ -332,4 +332,32 @@ void main() {
 // CHECK-NEXT:   [[query23:%\d+]] = OpImageQueryLevels %uint [[t9]]
 // CHECK-NEXT:                      OpStore %numLevels [[query23]]
   t9.GetDimensions(mipLevel, width, height, elements, numLevels);
+
+// Try with signed integer as argument.
+
+// CHECK:                [[t3:%\d+]] = OpLoad %type_2d_image %t3
+// CHECK-NEXT:        [[query:%\d+]] = OpImageQuerySizeLod %v2uint [[t3]] %int_0
+// CHECK-NEXT: [[query_0_uint:%\d+]] = OpCompositeExtract %uint [[query]] 0
+// CHECK-NEXT:  [[query_0_int:%\d+]] = OpBitcast %int [[query_0_uint]]
+// CHECK-NEXT:                         OpStore %signedWidth [[query_0_int]]
+// CHECK-NEXT: [[query_1_uint:%\d+]] = OpCompositeExtract %uint [[query]] 1
+// CHECK-NEXT:  [[query_1_int:%\d+]] = OpBitcast %int [[query_1_uint]]
+// CHECK-NEXT:                         OpStore %signedHeight [[query_1_int]]
+  int signedMipLevel, signedWidth, signedHeight, signedNumLevels;
+  t3.GetDimensions(signedWidth, signedHeight);
+
+// CHECK-NEXT:                [[t3:%\d+]] = OpLoad %type_2d_image %t3
+// CHECK-NEXT:    [[signedMipLevel:%\d+]] = OpLoad %int %signedMipLevel
+// CHECK-NEXT:  [[unsignedMipLevel:%\d+]] = OpBitcast %uint [[signedMipLevel]]
+// CHECK-NEXT:             [[query:%\d+]] = OpImageQuerySizeLod %v2uint [[t3]] [[unsignedMipLevel]]
+// CHECK-NEXT:      [[query_0_uint:%\d+]] = OpCompositeExtract %uint [[query]] 0
+// CHECK-NEXT:       [[query_0_int:%\d+]] = OpBitcast %int [[query_0_uint]]
+// CHECK-NEXT:                              OpStore %signedWidth [[query_0_int]]
+// CHECK-NEXT:      [[query_1_uint:%\d+]] = OpCompositeExtract %uint [[query]] 1
+// CHECK-NEXT:       [[query_1_int:%\d+]] = OpBitcast %int [[query_1_uint]]
+// CHECK-NEXT:                              OpStore %signedHeight [[query_1_int]]
+// CHECK-NEXT: [[query_levels_uint:%\d+]] = OpImageQueryLevels %uint [[t3]]
+// CHECK-NEXT:  [[query_levels_int:%\d+]] = OpBitcast %int [[query_levels_uint]]
+// CHECK-NEXT:                              OpStore %signedNumLevels [[query_levels_int]]
+  t3.GetDimensions(signedMipLevel, signedWidth, signedHeight, signedNumLevels);
 }