Browse Source

[spirv] Turn on legalization for invalid opcode (#1058)

Certain opcodes are not available in non-pixel stages.
Call the pass to replace them.
Lei Zhang 7 years ago
parent
commit
ae8c5febf7

+ 1 - 1
external/SPIRV-Tools

@@ -1 +1 @@
-Subproject commit 50e85c865ca9c4b53e2724f36a84fb2566c1ce97
+Subproject commit e7fafdaa68a3775be5f2406e91db4b5d3fbc7b35

+ 2 - 1
tools/clang/lib/SPIRV/DeclResultIdMapper.h

@@ -653,7 +653,8 @@ private:
   /// The following cases will require legalization:
   ///
   /// 1. Opaque types (textures, samplers) within structs
-  /// 2. Structured buffer assignments
+  /// 2. Structured buffer aliasing
+  /// 3. Using SPIR-V instructions not allowed in the currect shader stage
   ///
   /// This covers the second case:
   ///

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

@@ -3620,6 +3620,14 @@ uint32_t SPIRVEmitter::createImageSample(
     texelTypeId = theBuilder.getVecType(elemTypeId, 4);
   }
 
+  // The Lod and Grad image operands requires explicit-lod instructions.
+  // Otherwise we use implicit-lod instructions.
+  const bool isExplicit = lod || (grad.first && grad.second);
+
+  // Implicit-lod instructions are only allowed in pixel shader.
+  if (!shaderModel.IsPS() && !isExplicit)
+    needsLegalization = true;
+
   uint32_t retVal = theBuilder.createImageSample(
       texelTypeId, imageType, image, sampler, coordinate, compareVal, bias, lod,
       grad, constOffset, varOffset, constOffsets, sample, minLod,
@@ -7227,6 +7235,21 @@ uint32_t SPIRVEmitter::processIntrinsicF32ToF16(const CallExpr *callExpr) {
 
 uint32_t SPIRVEmitter::processIntrinsicUsingSpirvInst(
     const CallExpr *callExpr, spv::Op opcode, bool actPerRowForMatrices) {
+  // Certain opcodes are only allowed in pixel shader
+  if (!shaderModel.IsPS())
+    switch (opcode) {
+    case spv::Op::OpDPdx:
+    case spv::Op::OpDPdy:
+    case spv::Op::OpDPdxFine:
+    case spv::Op::OpDPdyFine:
+    case spv::Op::OpDPdxCoarse:
+    case spv::Op::OpDPdyCoarse:
+    case spv::Op::OpFwidth:
+    case spv::Op::OpFwidthFine:
+    case spv::Op::OpFwidthCoarse:
+      needsLegalization = true;
+    }
+
   const uint32_t returnType = typeTranslator.translateType(callExpr->getType());
   if (callExpr->getNumArgs() == 1u) {
     const Expr *arg = callExpr->getArg(0);

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

@@ -862,9 +862,10 @@ private:
   /// The following cases will require legalization:
   ///
   /// 1. Opaque types (textures, samplers) within structs
-  /// 2. Structured buffer assignments
+  /// 2. Structured buffer aliasing
+  /// 3. Using SPIR-V instructions not allowed in the currect shader stage
   ///
-  /// This covers the first case.
+  /// This covers the first and third case.
   ///
   /// If this is true, SPIRV-Tools legalization passes will be executed after
   /// the translation to legalize the generated SPIR-V binary.