Pārlūkot izejas kodu

[spirv] Refactoring: create dedicated functions for method calls (#687)

Lei Zhang 8 gadi atpakaļ
vecāks
revīzija
ea9f8cfbaf
2 mainītis faili ar 261 papildinājumiem un 223 dzēšanām
  1. 217 206
      tools/clang/lib/SPIRV/SPIRVEmitter.cpp
  2. 44 17
      tools/clang/lib/SPIRV/SPIRVEmitter.h

+ 217 - 206
tools/clang/lib/SPIRV/SPIRVEmitter.cpp

@@ -2010,68 +2010,35 @@ SpirvEvalInfo SPIRVEmitter::doCXXMemberCallExpr(const CXXMemberCallExpr *expr) {
 
   return processCall(expr);
 }
+void SPIRVEmitter::handleOptionalOffsetInMethodCall(
+    const CXXMemberCallExpr *expr, uint32_t index, uint32_t *constOffset,
+    uint32_t *varOffset) {
+  *constOffset = *varOffset = 0; // Initialize both first
+
+  if (expr->getNumArgs() == index + 1) { // Has offset argument
+    if (*constOffset = tryToEvaluateAsConst(expr->getArg(index)))
+      return; // Constant offset
+    else
+      *varOffset = doExpr(expr->getArg(index));
+  }
+};
 
 SpirvEvalInfo
 SPIRVEmitter::processIntrinsicMemberCall(const CXXMemberCallExpr *expr,
                                          hlsl::IntrinsicOp opcode) {
   using namespace hlsl;
 
-  // Handles the offset argument. If there exists an offset argument, writes the
-  // <result-id> to either *constOffset or *varOffset, depending on the
-  // constantness of the offset.
-  const auto handleOffset = [this](const CXXMemberCallExpr *expr,
-                                   uint32_t index, uint32_t *constOffset,
-                                   uint32_t *varOffset) {
-    *constOffset = *varOffset = 0; // Initialize both first
-
-    if (expr->getNumArgs() == index + 1) { // Has offset argument
-      if (*constOffset = tryToEvaluateAsConst(expr->getArg(index)))
-        return; // Constant offset
-      else
-        *varOffset = doExpr(expr->getArg(index));
-    }
-  };
-
-  const FunctionDecl *callee = expr->getDirectCallee();
-  const auto retType = typeTranslator.translateType(callee->getReturnType());
-
   switch (opcode) {
   case IntrinsicOp::MOP_Sample:
-  case IntrinsicOp::MOP_Gather: {
-    // Signatures:
-    // DXGI_FORMAT Object.Sample(sampler_state S,
-    //                           float Location
-    //                           [, int Offset]);
-    //
-    // <Template Type>4 Object.Gather(sampler_state S,
-    //                                float2|3|4 Location
-    //                                [, int2 Offset]);
-
-    const auto *imageExpr = expr->getImplicitObjectArgument();
-
-    const uint32_t imageType =
-        typeTranslator.translateType(imageExpr->getType());
-
-    const uint32_t image = loadIfGLValue(imageExpr);
-    const uint32_t sampler = doExpr(expr->getArg(0));
-    const uint32_t coordinate = doExpr(expr->getArg(1));
-    // .Sample()/.Gather() has a third optional paramter for offset.
-    uint32_t constOffset = 0, varOffset = 0;
-    handleOffset(expr, 2, &constOffset, &varOffset);
-
-    if (opcode == IntrinsicOp::MOP_Sample) {
-      return theBuilder.createImageSample(
-          retType, imageType, image, sampler, coordinate, /*bias*/ 0,
-          /*lod*/ 0, std::make_pair(0, 0), constOffset, varOffset,
-          /*constOffsets*/ 0, /*sampleNumber*/ 0);
-    } else {
-      return theBuilder.createImageGather(
-          retType, imageType, image, sampler, coordinate,
-          // .Gather() doc says we return four components of red data.
-          theBuilder.getConstantInt32(0), constOffset, varOffset,
-          /*constOffsets*/ 0, /*sampleNumber*/ 0);
-    }
-  }
+    return processTextureSampleGather(expr, /*isSample=*/true);
+  case IntrinsicOp::MOP_Gather:
+    return processTextureSampleGather(expr, /*isSample=*/false);
+  case IntrinsicOp::MOP_SampleBias:
+    return processTextureSampleBiasLevel(expr, /*isBias=*/true);
+  case IntrinsicOp::MOP_SampleLevel:
+    return processTextureSampleBiasLevel(expr, /*isBias=*/false);
+  case IntrinsicOp::MOP_SampleGrad:
+    return processTextureSampleGrad(expr);
   case IntrinsicOp::MOP_GatherRed:
     return processTextureGatherRGBA(expr, 0);
   case IntrinsicOp::MOP_GatherGreen:
@@ -2080,166 +2047,29 @@ SPIRVEmitter::processIntrinsicMemberCall(const CXXMemberCallExpr *expr,
     return processTextureGatherRGBA(expr, 2);
   case IntrinsicOp::MOP_GatherAlpha:
     return processTextureGatherRGBA(expr, 3);
-  case IntrinsicOp::MOP_SampleBias:
-  case IntrinsicOp::MOP_SampleLevel: {
-    // Signatures:
-    // DXGI_FORMAT Object.SampleBias(sampler_state S,
-    //                               float Location,
-    //                               float Bias
-    //                               [, int Offset]);
-    //
-    // DXGI_FORMAT Object.SampleLevel(sampler_state S,
-    //                                float Location,
-    //                                float LOD
-    //                                [, int Offset]);
-    const auto *imageExpr = expr->getImplicitObjectArgument();
-
-    const uint32_t imageType =
-        typeTranslator.translateType(imageExpr->getType());
-
-    const uint32_t image = loadIfGLValue(imageExpr);
-    const uint32_t sampler = doExpr(expr->getArg(0));
-    const uint32_t coordinate = doExpr(expr->getArg(1));
-    uint32_t lod = 0;
-    uint32_t bias = 0;
-    if (opcode == IntrinsicOp::MOP_SampleBias) {
-      bias = doExpr(expr->getArg(2));
-    } else {
-      lod = doExpr(expr->getArg(2));
-    }
-    // .Bias()/.SampleLevel() has a fourth optional paramter for offset.
-    uint32_t constOffset = 0, varOffset = 0;
-    handleOffset(expr, 3, &constOffset, &varOffset);
-
-    return theBuilder.createImageSample(
-        retType, imageType, image, sampler, coordinate, bias, lod,
-        std::make_pair(0, 0), constOffset, varOffset, /*constOffsets*/ 0,
-        /*sampleNumber*/ 0);
-  }
-  case IntrinsicOp::MOP_SampleGrad: {
-    // Signature:
-    // DXGI_FORMAT Object.SampleGrad(sampler_state S,
-    //                               float Location,
-    //                               float DDX,
-    //                               float DDY
-    //                               [, int Offset]);
-
-    const auto *imageExpr = expr->getImplicitObjectArgument();
-
-    const uint32_t imageType =
-        typeTranslator.translateType(imageExpr->getType());
-
-    const uint32_t image = loadIfGLValue(imageExpr);
-    const uint32_t sampler = doExpr(expr->getArg(0));
-    const uint32_t coordinate = doExpr(expr->getArg(1));
-    const uint32_t ddx = doExpr(expr->getArg(2));
-    const uint32_t ddy = doExpr(expr->getArg(3));
-    // .SampleGrad() has a fifth optional paramter for offset.
-    uint32_t constOffset = 0, varOffset = 0;
-    handleOffset(expr, 4, &constOffset, &varOffset);
-
-    return theBuilder.createImageSample(
-        retType, imageType, image, sampler, coordinate, /*bias*/ 0, /*lod*/ 0,
-        std::make_pair(ddx, ddy), constOffset, varOffset, /*constOffsets*/ 0,
-        /*sampleNumber*/ 0);
-  }
-  case IntrinsicOp::MOP_Load: {
-    // Signature:
-    // ret Object.Load(int Location
-    //                 [, int SampleIndex,]
-    //                 [, int Offset]);
-
-    const auto *object = expr->getImplicitObjectArgument();
-    const auto *location = expr->getArg(0);
-    const auto objectType = object->getType();
-
-    if (typeTranslator.isRWByteAddressBuffer(objectType) ||
-        typeTranslator.isByteAddressBuffer(objectType))
-      return processByteAddressBufferLoadStore(expr, 1, /*doStore*/ false);
-
-    if (TypeTranslator::isStructuredBuffer(objectType))
-      return processStructuredBufferLoad(expr);
-
-    if (TypeTranslator::isBuffer(objectType) ||
-        TypeTranslator::isRWBuffer(objectType) ||
-        TypeTranslator::isRWTexture(objectType))
-      return processBufferTextureLoad(object, doExpr(location));
-
-    if (TypeTranslator::isTexture(objectType)) {
-      // .Load() has a second optional paramter for offset.
-      const auto locationId = doExpr(location);
-      uint32_t constOffset = 0, varOffset = 0;
-      uint32_t coordinate = locationId, lod = 0;
-
-      if (TypeTranslator::isTextureMS(objectType)) {
-        // SampleIndex is only available when the Object is of Texture2DMS or
-        // Texture2DMSArray types. Under those cases, Offset will be the third
-        // parameter (index 2).
-        lod = doExpr(expr->getArg(1));
-        handleOffset(expr, 2, &constOffset, &varOffset);
-      } else {
-        // For Texture Load() functions, the location parameter is a vector
-        // that consists of both the coordinate and the mipmap level (via the
-        // last vector element). We need to split it here since the
-        // OpImageFetch SPIR-V instruction encodes them as separate arguments.
-        splitVecLastElement(location->getType(), locationId, &coordinate, &lod);
-        // For textures other than Texture2DMS(Array), offset should be the
-        // second parameter (index 1).
-        handleOffset(expr, 1, &constOffset, &varOffset);
-      }
-
-      return processBufferTextureLoad(object, coordinate, constOffset,
-                                      varOffset, lod);
-    }
-    emitError("Load() is not implemented for the given object type.");
-    return 0;
-  }
-  case IntrinsicOp::MOP_Load2: {
+  case IntrinsicOp::MOP_Load:
+    return processBufferTextureLoad(expr);
+  case IntrinsicOp::MOP_Load2:
     return processByteAddressBufferLoadStore(expr, 2, /*doStore*/ false);
-  }
-  case IntrinsicOp::MOP_Load3: {
+  case IntrinsicOp::MOP_Load3:
     return processByteAddressBufferLoadStore(expr, 3, /*doStore*/ false);
-  }
-  case IntrinsicOp::MOP_Load4: {
+  case IntrinsicOp::MOP_Load4:
     return processByteAddressBufferLoadStore(expr, 4, /*doStore*/ false);
-  }
-  case IntrinsicOp::MOP_Store: {
+  case IntrinsicOp::MOP_Store:
     return processByteAddressBufferLoadStore(expr, 1, /*doStore*/ true);
-  }
-  case IntrinsicOp::MOP_Store2: {
+  case IntrinsicOp::MOP_Store2:
     return processByteAddressBufferLoadStore(expr, 2, /*doStore*/ true);
-  }
-  case IntrinsicOp::MOP_Store3: {
+  case IntrinsicOp::MOP_Store3:
     return processByteAddressBufferLoadStore(expr, 3, /*doStore*/ true);
-  }
-  case IntrinsicOp::MOP_Store4: {
+  case IntrinsicOp::MOP_Store4:
     return processByteAddressBufferLoadStore(expr, 4, /*doStore*/ true);
-  }
+  case IntrinsicOp::MOP_GetDimensions:
+    return processGetDimensions(expr);
+  case IntrinsicOp::MOP_CalculateLevelOfDetail:
+    return processTextureLevelOfDetail(expr);
   case IntrinsicOp::MOP_Append:
-  case IntrinsicOp::MOP_Consume: {
+  case IntrinsicOp::MOP_Consume:
     return processACSBufferAppendConsume(expr);
-  }
-  case IntrinsicOp::MOP_GetDimensions: {
-    const auto objectType = expr->getImplicitObjectArgument()->getType();
-    if (TypeTranslator::isTexture(objectType) ||
-        TypeTranslator::isRWTexture(objectType) ||
-        TypeTranslator::isBuffer(objectType) ||
-        TypeTranslator::isRWBuffer(objectType)) {
-      return processBufferTextureGetDimensions(expr);
-    } else if (TypeTranslator::isByteAddressBuffer(objectType) ||
-               TypeTranslator::isRWByteAddressBuffer(objectType) ||
-               TypeTranslator::isStructuredBuffer(objectType) ||
-               TypeTranslator::isAppendStructuredBuffer(objectType) ||
-               TypeTranslator::isConsumeStructuredBuffer(objectType)) {
-      return processByteAddressBufferStructuredBufferGetDimensions(expr);
-    } else {
-      emitError("GetDimensions not implmented for the given type yet.");
-      return 0;
-    }
-  }
-  case IntrinsicOp::MOP_CalculateLevelOfDetail: {
-    return processTextureLevelOfDetail(expr);
-  }
   case IntrinsicOp::MOP_InterlockedAdd:
   case IntrinsicOp::MOP_InterlockedAnd:
   case IntrinsicOp::MOP_InterlockedOr:
@@ -2255,10 +2085,191 @@ SPIRVEmitter::processIntrinsicMemberCall(const CXXMemberCallExpr *expr,
   }
 
   emitError("HLSL intrinsic member call unimplemented: %0")
-      << callee->getName();
+      << expr->getDirectCallee()->getName();
+  return 0;
+}
+
+uint32_t SPIRVEmitter::processTextureSampleGather(const CXXMemberCallExpr *expr,
+                                                  const bool isSample) {
+  // Signatures:
+  // DXGI_FORMAT Object.Sample(sampler_state S,
+  //                           float Location
+  //                           [, int Offset]);
+  //
+  // <Template Type>4 Object.Gather(sampler_state S,
+  //                                float2|3|4 Location
+  //                                [, int2 Offset]);
+
+  const auto *imageExpr = expr->getImplicitObjectArgument();
+
+  const uint32_t imageType = typeTranslator.translateType(imageExpr->getType());
+
+  const uint32_t image = loadIfGLValue(imageExpr);
+  const uint32_t sampler = doExpr(expr->getArg(0));
+  const uint32_t coordinate = doExpr(expr->getArg(1));
+  // .Sample()/.Gather() has a third optional paramter for offset.
+  uint32_t constOffset = 0, varOffset = 0;
+  handleOptionalOffsetInMethodCall(expr, 2, &constOffset, &varOffset);
+
+  const auto retType =
+      typeTranslator.translateType(expr->getDirectCallee()->getReturnType());
+
+  if (isSample) {
+    return theBuilder.createImageSample(
+        retType, imageType, image, sampler, coordinate, /*bias*/ 0,
+        /*lod*/ 0, std::make_pair(0, 0), constOffset, varOffset,
+        /*constOffsets*/ 0, /*sampleNumber*/ 0);
+  } else {
+    return theBuilder.createImageGather(
+        retType, imageType, image, sampler, coordinate,
+        // .Gather() doc says we return four components of red data.
+        theBuilder.getConstantInt32(0), constOffset, varOffset,
+        /*constOffsets*/ 0, /*sampleNumber*/ 0);
+  }
+}
+
+uint32_t
+SPIRVEmitter::processTextureSampleBiasLevel(const CXXMemberCallExpr *expr,
+                                            const bool isBias) {
+  // Signatures:
+  // DXGI_FORMAT Object.SampleBias(sampler_state S,
+  //                               float Location,
+  //                               float Bias
+  //                               [, int Offset]);
+  //
+  // DXGI_FORMAT Object.SampleLevel(sampler_state S,
+  //                                float Location,
+  //                                float LOD
+  //                                [, int Offset]);
+  const auto *imageExpr = expr->getImplicitObjectArgument();
+
+  const uint32_t imageType = typeTranslator.translateType(imageExpr->getType());
+
+  const uint32_t image = loadIfGLValue(imageExpr);
+  const uint32_t sampler = doExpr(expr->getArg(0));
+  const uint32_t coordinate = doExpr(expr->getArg(1));
+  uint32_t lod = 0;
+  uint32_t bias = 0;
+  if (isBias) {
+    bias = doExpr(expr->getArg(2));
+  } else {
+    lod = doExpr(expr->getArg(2));
+  }
+  // .Bias()/.SampleLevel() has a fourth optional paramter for offset.
+  uint32_t constOffset = 0, varOffset = 0;
+  handleOptionalOffsetInMethodCall(expr, 3, &constOffset, &varOffset);
+
+  const auto retType =
+      typeTranslator.translateType(expr->getDirectCallee()->getReturnType());
+
+  return theBuilder.createImageSample(
+      retType, imageType, image, sampler, coordinate, bias, lod,
+      std::make_pair(0, 0), constOffset, varOffset, /*constOffsets*/ 0,
+      /*sampleNumber*/ 0);
+}
+
+uint32_t SPIRVEmitter::processTextureSampleGrad(const CXXMemberCallExpr *expr) {
+  // Signature:
+  // DXGI_FORMAT Object.SampleGrad(sampler_state S,
+  //                               float Location,
+  //                               float DDX,
+  //                               float DDY
+  //                               [, int Offset]);
+
+  const auto *imageExpr = expr->getImplicitObjectArgument();
+
+  const uint32_t imageType = typeTranslator.translateType(imageExpr->getType());
+
+  const uint32_t image = loadIfGLValue(imageExpr);
+  const uint32_t sampler = doExpr(expr->getArg(0));
+  const uint32_t coordinate = doExpr(expr->getArg(1));
+  const uint32_t ddx = doExpr(expr->getArg(2));
+  const uint32_t ddy = doExpr(expr->getArg(3));
+  // .SampleGrad() has a fifth optional paramter for offset.
+  uint32_t constOffset = 0, varOffset = 0;
+  handleOptionalOffsetInMethodCall(expr, 4, &constOffset, &varOffset);
+
+  const auto retType =
+      typeTranslator.translateType(expr->getDirectCallee()->getReturnType());
+
+  return theBuilder.createImageSample(
+      retType, imageType, image, sampler, coordinate, /*bias*/ 0, /*lod*/ 0,
+      std::make_pair(ddx, ddy), constOffset, varOffset, /*constOffsets*/ 0,
+      /*sampleNumber*/ 0);
+}
+
+SpirvEvalInfo
+SPIRVEmitter::processBufferTextureLoad(const CXXMemberCallExpr *expr) {
+  // Signature:
+  // ret Object.Load(int Location
+  //                 [, int SampleIndex,]
+  //                 [, int Offset]);
+
+  const auto *object = expr->getImplicitObjectArgument();
+  const auto *location = expr->getArg(0);
+  const auto objectType = object->getType();
+
+  if (typeTranslator.isRWByteAddressBuffer(objectType) ||
+      typeTranslator.isByteAddressBuffer(objectType))
+    return processByteAddressBufferLoadStore(expr, 1, /*doStore*/ false);
+
+  if (TypeTranslator::isStructuredBuffer(objectType))
+    return processStructuredBufferLoad(expr);
+
+  if (TypeTranslator::isBuffer(objectType) ||
+      TypeTranslator::isRWBuffer(objectType) ||
+      TypeTranslator::isRWTexture(objectType))
+    return processBufferTextureLoad(object, doExpr(location));
+
+  if (TypeTranslator::isTexture(objectType)) {
+    // .Load() has a second optional paramter for offset.
+    const auto locationId = doExpr(location);
+    uint32_t constOffset = 0, varOffset = 0;
+    uint32_t coordinate = locationId, lod = 0;
+
+    if (TypeTranslator::isTextureMS(objectType)) {
+      // SampleIndex is only available when the Object is of Texture2DMS or
+      // Texture2DMSArray types. Under those cases, Offset will be the third
+      // parameter (index 2).
+      lod = doExpr(expr->getArg(1));
+      handleOptionalOffsetInMethodCall(expr, 2, &constOffset, &varOffset);
+    } else {
+      // For Texture Load() functions, the location parameter is a vector
+      // that consists of both the coordinate and the mipmap level (via the
+      // last vector element). We need to split it here since the
+      // OpImageFetch SPIR-V instruction encodes them as separate arguments.
+      splitVecLastElement(location->getType(), locationId, &coordinate, &lod);
+      // For textures other than Texture2DMS(Array), offset should be the
+      // second parameter (index 1).
+      handleOptionalOffsetInMethodCall(expr, 1, &constOffset, &varOffset);
+    }
+
+    return processBufferTextureLoad(object, coordinate, constOffset, varOffset,
+                                    lod);
+  }
+  emitError("Load() is not implemented for the given object type.");
   return 0;
 }
 
+uint32_t SPIRVEmitter::processGetDimensions(const CXXMemberCallExpr *expr) {
+  const auto objectType = expr->getImplicitObjectArgument()->getType();
+  if (TypeTranslator::isTexture(objectType) ||
+      TypeTranslator::isRWTexture(objectType) ||
+      TypeTranslator::isBuffer(objectType) ||
+      TypeTranslator::isRWBuffer(objectType)) {
+    return processBufferTextureGetDimensions(expr);
+  } else if (TypeTranslator::isByteAddressBuffer(objectType) ||
+             TypeTranslator::isRWByteAddressBuffer(objectType) ||
+             TypeTranslator::isStructuredBuffer(objectType) ||
+             TypeTranslator::isAppendStructuredBuffer(objectType) ||
+             TypeTranslator::isConsumeStructuredBuffer(objectType)) {
+    return processByteAddressBufferStructuredBufferGetDimensions(expr);
+  } else {
+    emitError("GetDimensions not implmented for the given type yet.");
+    return 0;
+  }
+}
+
 SpirvEvalInfo
 SPIRVEmitter::doCXXOperatorCallExpr(const CXXOperatorCallExpr *expr) {
   { // Handle Buffer/RWBuffer/Texture/RWTexture indexing

+ 44 - 17
tools/clang/lib/SPIRV/SPIRVEmitter.h

@@ -467,13 +467,17 @@ private:
   void processSwitchStmtUsingIfStmts(const SwitchStmt *switchStmt);
 
 private:
-  /// \brief Loads numWords 32-bit unsigned integers or stores numWords 32-bit
-  /// unsigned integers (based on the doStore parameter) to the given
-  /// ByteAddressBuffer. Loading is allowed from a ByteAddressBuffer or
-  /// RWByteAddressBuffer. Storing is allowed only to RWByteAddressBuffer.
-  /// Panics if it is not the case.
-  uint32_t processByteAddressBufferLoadStore(const CXXMemberCallExpr *,
-                                             uint32_t numWords, bool doStore);
+  /// Handles the optional offset argument in the given method call at the given
+  /// argument index.
+  /// If there exists an offset argument, writes the <result-id> to either
+  /// *constOffset or *varOffset, depending on the constantness of the offset.
+  void handleOptionalOffsetInMethodCall(const CXXMemberCallExpr *expr,
+                                        uint32_t index, uint32_t *constOffset,
+                                        uint32_t *varOffset);
+
+  /// \brief Processes .Load() method call for Buffer/RWBuffer and texture
+  /// objects.
+  SpirvEvalInfo processBufferTextureLoad(const CXXMemberCallExpr *);
 
   /// \brief Loads one element from the given Buffer/RWBuffer/Texture object at
   /// the given location. The type of the loaded element matches the type in the
@@ -482,29 +486,47 @@ private:
                                     uint32_t constOffset = 0,
                                     uint32_t varOffst = 0, uint32_t lod = 0);
 
-  /// \brief Generates an OpAccessChain instruction for the given
-  /// (RW)StructuredBuffer.Load() method call.
-  SpirvEvalInfo processStructuredBufferLoad(const CXXMemberCallExpr *expr);
+  /// \brief Processes .Sample() and .Gather() method calls for texture objects.
+  uint32_t processTextureSampleGather(const CXXMemberCallExpr *expr,
+                                      bool isSample);
 
-  /// \brief Generates SPIR-V instructions for the .Append()/.Consume() call on
-  /// the given {Append|Consume}StructuredBuffer. Returns the <result-id> of
-  /// the loaded value for .Consume; returns zero for .Append().
-  SpirvEvalInfo processACSBufferAppendConsume(const CXXMemberCallExpr *expr);
+  /// \brief Processes .SampleBias() and .SampleLevel() method calls for texture
+  /// objects.
+  uint32_t processTextureSampleBiasLevel(const CXXMemberCallExpr *expr,
+                                         bool isBias);
 
-  /// \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);
+  /// \brief Processes .SampleGrad()  method call for texture objects.
+  uint32_t processTextureSampleGrad(const CXXMemberCallExpr *expr);
 
   /// \brief Handles .Gather{Red|Green|Blue|Alpha}() calls on texture types.
   uint32_t processTextureGatherRGBA(const CXXMemberCallExpr *expr,
                                     uint32_t component);
 
+  /// \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);
+
+  /// \brief Processes the .GetDimensions() call on supported objects.
+  uint32_t processGetDimensions(const CXXMemberCallExpr *);
+
   /// \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
   /// following info can be queried: width, height, depth, number of mipmap
   /// levels.
   uint32_t processBufferTextureGetDimensions(const CXXMemberCallExpr *);
 
+  /// \brief Generates an OpAccessChain instruction for the given
+  /// (RW)StructuredBuffer.Load() method call.
+  SpirvEvalInfo processStructuredBufferLoad(const CXXMemberCallExpr *expr);
+
+  /// \brief Loads numWords 32-bit unsigned integers or stores numWords 32-bit
+  /// unsigned integers (based on the doStore parameter) to the given
+  /// ByteAddressBuffer. Loading is allowed from a ByteAddressBuffer or
+  /// RWByteAddressBuffer. Storing is allowed only to RWByteAddressBuffer.
+  /// Panics if it is not the case.
+  uint32_t processByteAddressBufferLoadStore(const CXXMemberCallExpr *,
+                                             uint32_t numWords, bool doStore);
+
   /// \brief Processes the GetDimensions intrinsic function call on a
   /// (RW)ByteAddressBuffer by querying the image in the given expr.
   uint32_t processByteAddressBufferStructuredBufferGetDimensions(
@@ -515,6 +537,11 @@ private:
   uint32_t processRWByteAddressBufferAtomicMethods(hlsl::IntrinsicOp opcode,
                                                    const CXXMemberCallExpr *);
 
+  /// \brief Generates SPIR-V instructions for the .Append()/.Consume() call on
+  /// the given {Append|Consume}StructuredBuffer. Returns the <result-id> of
+  /// the loaded value for .Consume; returns zero for .Append().
+  SpirvEvalInfo processACSBufferAppendConsume(const CXXMemberCallExpr *expr);
+
 private:
   /// \brief Wrapper method to create a fatal error message and report it
   /// in the diagnostic engine associated with this consumer.