Browse Source

Support obsolete semantics with -Gec flag (#1552)

* Support obsolete semantics with -Gec flag

Shaders with obsoleted semantics now compile with -Gec flag. Each
semantic will trigger a warning and be remapped to the current name.

The obsolete semantics & remappings introduced in this change are:

POSITION -> SV_Position (VS output)
VPOS     -> SV_Position (PS input)
COLOR    -> SV_Target   (PS output)
DEPTH    -> SV_Depth    (PS output)

* Switch to case insensitive compare; add tests

* Address code review feedback
Helena Kotas 7 years ago
parent
commit
7f6667cd88

+ 2 - 0
include/dxc/HLSL/DxilTypeSystem.h

@@ -202,6 +202,8 @@ private:
 
 DXIL::SigPointKind SigPointFromInputQual(DxilParamInputQual Q, DXIL::ShaderKind SK, bool isPC);
 
+void RemapObsoleteSemantic(DxilParameterAnnotation &paramInfo, DXIL::SigPointKind sigPoint, llvm::LLVMContext &Context);
+
 class DxilStructTypeIterator
     : public std::iterator<std::input_iterator_tag,
                            std::pair<llvm::Type *, DxilFieldAnnotation *>> {

+ 3 - 2
include/dxc/HLSL/HLModule.h

@@ -49,7 +49,7 @@ class RootSignatureHandle;
 struct HLOptions {
   HLOptions()
       : bDefaultRowMajor(false), bIEEEStrict(false), bDisableOptimizations(false),
-        bLegacyCBufferLoad(false), PackingStrategy(0), unused(0) {
+        bLegacyCBufferLoad(false), PackingStrategy(0), bBackCompatMode(0), unused(0) {
   }
   uint32_t GetHLOptionsRaw() const;
   void SetHLOptionsRaw(uint32_t data);
@@ -61,7 +61,8 @@ struct HLOptions {
   unsigned PackingStrategy         : 2;
   static_assert((unsigned)DXIL::PackingStrategy::Invalid < 4, "otherwise 2 bits is not enough to store PackingStrategy");
   unsigned bUseMinPrecision        : 1;
-  unsigned unused                  : 24;
+  unsigned bBackCompatMode         : 1;
+  unsigned unused                  : 23;
 };
 
 typedef std::unordered_map<const llvm::Function *, std::unique_ptr<DxilFunctionProps>> DxilFunctionPropsMap;

+ 1 - 0
include/llvm/IR/LLVMContext.h

@@ -168,6 +168,7 @@ public:
   void emitError(unsigned LocCookie, const Twine &ErrorStr);
   void emitError(const Instruction *I, const Twine &ErrorStr);
   void emitError(const Twine &ErrorStr);
+  void emitWarning(const Twine &WarningStr); // HLSL Change
 
   /// \brief Query for a debug option's value.
   ///

+ 41 - 0
lib/HLSL/DxilTypeSystem.cpp

@@ -412,6 +412,47 @@ DXIL::SigPointKind SigPointFromInputQual(DxilParamInputQual Q, DXIL::ShaderKind
   return DXIL::SigPointKind::Invalid;
 }
 
+void RemapSemantic(llvm::StringRef &oldSemName, llvm::StringRef &oldSemFullName, const char *newSemName,
+  DxilParameterAnnotation &paramInfo, llvm::LLVMContext &Context) {
+  // format deprecation warning
+  Context.emitWarning(Twine("DX9-style semantic \"") + oldSemName + Twine("\" mapped to DX10 system semantic \"") + newSemName +
+    Twine("\" due to -Gec flag. This functionality is deprecated in newer language versions."));
+
+  // create new semantic name with the same index
+  std::string newSemNameStr(newSemName);
+  unsigned indexLen = oldSemFullName.size() - oldSemName.size();
+  if (indexLen > 0) {
+    newSemNameStr = newSemNameStr.append(oldSemFullName.data() + oldSemName.size(), indexLen);
+  }
+
+  paramInfo.SetSemanticString(newSemNameStr);
+}
+
+void RemapObsoleteSemantic(DxilParameterAnnotation &paramInfo, DXIL::SigPointKind sigPoint, llvm::LLVMContext &Context) {
+  DXASSERT(paramInfo.HasSemanticString(), "expected paramInfo with semantic");
+  //*ppWarningMsg = nullptr;
+
+  llvm::StringRef semFullName = paramInfo.GetSemanticStringRef();
+  llvm::StringRef semName;
+  unsigned semIndex;
+  Semantic::DecomposeNameAndIndex(semFullName, &semName, &semIndex);
+
+  if (sigPoint == DXIL::SigPointKind::PSOut) {
+    if (semName.size() == 5) {
+      if (strnicmp(semName.data(), "COLOR", 5) == 0) {
+        RemapSemantic(semName, semFullName, "SV_Target", paramInfo, Context);
+      }
+      else if (strnicmp(semName.data(), "DEPTH", 5) == 0) {
+        RemapSemantic(semName, semFullName, "SV_Depth", paramInfo, Context);
+      }
+    }
+  }
+  else if ((sigPoint == DXIL::SigPointKind::VSOut && semName.size() == 8 && strnicmp(semName.data(), "POSITION", 8) == 0) ||
+           (sigPoint == DXIL::SigPointKind::PSIn  && semName.size() == 4 && strnicmp(semName.data(), "VPOS", 4) == 0)) {
+    RemapSemantic(semName, semFullName, "SV_Position", paramInfo, Context);
+  }
+}
+
 bool DxilTypeSystem::UseMinPrecision() {
   if (m_LowPrecisionMode == DXIL::LowPrecisionMode::Undefined) {
     if (m_pModule->HasDxilModule()) {

+ 5 - 0
lib/HLSL/HLSignatureLower.cpp

@@ -230,6 +230,11 @@ void HLSignatureLower::ProcessArgument(Function *func,
       interpMode = InterpolationMode::Kind::Constant;
   }
 
+  //  back-compat mode - remap obsolete semantics
+  if (HLM.GetHLOptions().bBackCompatMode && paramAnnotation.HasSemanticString()) {
+    hlsl::RemapObsoleteSemantic(paramAnnotation, sigPoint->GetKind(), HLM.GetCtx());
+  }
+
   llvm::StringRef semanticStr = paramAnnotation.GetSemanticString();
   if (semanticStr.empty()) {
     func->getContext().emitError(

+ 3 - 0
lib/HLSL/HLSignatureLower.h

@@ -17,6 +17,7 @@ namespace llvm {
 class Value;
 class Argument;
 class Function;
+class StringRef;
 } // namespace llvm
 
 namespace hlsl {
@@ -26,6 +27,8 @@ class DxilFunctionAnnotation;
 class ShaderModel;
 struct DxilFunctionProps;
 class DxilSignatureElement;
+class DxilParameterAnnotation;
+class SigPoint;
 
 class HLSignatureLower {
 public:

+ 7 - 0
lib/IR/LLVMContext.cpp

@@ -170,6 +170,13 @@ void LLVMContext::emitError(const Twine &ErrorStr) {
   diagnose(DiagnosticInfoInlineAsm(ErrorStr));
 }
 
+// HLSL Change Start
+void LLVMContext::emitWarning(const Twine &WarningStr) {
+  diagnose(DiagnosticInfoInlineAsm(WarningStr, DiagnosticSeverity::DS_Warning));
+}
+// HLSL Change End
+
+
 void LLVMContext::emitError(const Instruction *I, const Twine &ErrorStr) {
   assert (I && "Invalid instruction");
   diagnose(DiagnosticInfoInlineAsm(*I, ErrorStr));

+ 22 - 3
tools/clang/lib/CodeGen/CGHLSLMS.cpp

@@ -205,6 +205,10 @@ private:
                                 DxilParamInputQual paramQual,
                                 llvm::StringRef semFullName,
                                 bool isPatchConstantFunction);
+
+  void RemapObsoleteSemantic(DxilParameterAnnotation &paramInfo,
+                             bool isPatchConstantFunction);
+
   void SetEntryFunction();
   SourceLocation SetSemantic(const NamedDecl *decl,
                              DxilParameterAnnotation &paramInfo);
@@ -381,6 +385,7 @@ CGMSHLSLRuntime::CGMSHLSLRuntime(CodeGenModule &CGM)
   opts.PackingStrategy = CGM.getCodeGenOpts().HLSLSignaturePackingStrategy;
 
   opts.bUseMinPrecision = CGM.getLangOpts().UseMinPrecision;
+  opts.bBackCompatMode = CGM.getLangOpts().EnableBackCompatMode;
 
   m_pHLModule->SetHLOptions(opts);
   m_pHLModule->SetAutoBindingSpace(CGM.getCodeGenOpts().HLSLDefaultSpace);
@@ -477,10 +482,9 @@ void CGMSHLSLRuntime::CheckParameterAnnotation(
       Semantic::GetByName(semName, sigPoint, SM->GetMajor(), SM->GetMinor());
   if (pSemantic->IsInvalid()) {
     DiagnosticsEngine &Diags = CGM.getDiags();
-    const ShaderModel *shader = m_pHLModule->GetShaderModel();
     unsigned DiagID =
-        Diags.getCustomDiagID(DiagnosticsEngine::Error, "invalid semantic '%0' for %1 %2.%3");
-    Diags.Report(SLoc, DiagID) << semName << shader->GetKindName() << shader->GetMajor() << shader->GetMinor();
+      Diags.getCustomDiagID(DiagnosticsEngine::Error, "invalid semantic '%0' for %1 %2.%3");
+    Diags.Report(SLoc, DiagID) << semName << SM->GetKindName() << SM->GetMajor() << SM->GetMinor();
   }
 }
 
@@ -1555,6 +1559,9 @@ void CGMSHLSLRuntime::AddHLSLFunctionInfo(Function *F, const FunctionDecl *FD) {
   SourceLocation retTySemanticLoc = SetSemantic(FD, retTyAnnotation);
   retTyAnnotation.SetParamInputQual(DxilParamInputQual::Out);
   if (isEntry) {
+    if (CGM.getLangOpts().EnableBackCompatMode && retTyAnnotation.HasSemanticString()) {
+      RemapObsoleteSemantic(retTyAnnotation, /*isPatchConstantFunction*/ false);
+    }
     CheckParameterAnnotation(retTySemanticLoc, retTyAnnotation,
                              /*isPatchConstantFunction*/ false);
   }
@@ -1833,6 +1840,9 @@ void CGMSHLSLRuntime::AddHLSLFunctionInfo(Function *F, const FunctionDecl *FD) {
 
     paramAnnotation.SetParamInputQual(dxilInputQ);
     if (isEntry) {
+      if (CGM.getLangOpts().EnableBackCompatMode && paramAnnotation.HasSemanticString()) {
+        RemapObsoleteSemantic(paramAnnotation, /*isPatchConstantFunction*/ false);
+      }
       CheckParameterAnnotation(paramSemanticLoc, paramAnnotation,
                                /*isPatchConstantFunction*/ false);
     }
@@ -1930,6 +1940,15 @@ void CGMSHLSLRuntime::AddHLSLFunctionInfo(Function *F, const FunctionDecl *FD) {
   }
 }
 
+void CGMSHLSLRuntime::RemapObsoleteSemantic(DxilParameterAnnotation &paramInfo, bool isPatchConstantFunction) {
+  DXASSERT(CGM.getLangOpts().EnableBackCompatMode, "should be used only in back-compat mode");
+
+  const ShaderModel *SM = m_pHLModule->GetShaderModel();
+  DXIL::SigPointKind sigPointKind = SigPointFromInputQual(paramInfo.GetParamInputQual(), SM->GetKind(), isPatchConstantFunction);
+
+  hlsl::RemapObsoleteSemantic(paramInfo, sigPointKind, CGM.getLLVMContext());
+}
+
 void CGMSHLSLRuntime::EmitHLSLFunctionProlog(Function *F, const FunctionDecl *FD) {
   // Support clip plane need debug info which not available when create function attribute.
   if (const HLSLClipPlanesAttr *Attr = FD->getAttr<HLSLClipPlanesAttr>()) {

+ 22 - 0
tools/clang/test/CodeGenHLSL/quick-test/obsolete_semantics_ps_1.hlsl

@@ -0,0 +1,22 @@
+// RUN: %dxc -E main -T ps_6_0 %s -Gec | FileCheck %s
+
+// CHECK: SV_Position              0   xyzw        0      POS   float
+// CHECK: SV_Target                1   xyzw        1   TARGET   float   xyzw
+// CHECK: SV_Depth                 0    N/A   oDepth    DEPTH   float    YES
+
+struct PSIn
+{
+ float4 Position;
+};
+
+struct PSOut
+{
+  float4 c : COLOR1;
+  float d  : DEPTH;
+};
+
+PSOut main(PSIn In : VPOS) 
+{
+    PSOut retValue = { {1, 0, 1, 0}, 0.5 };
+    return retValue;
+}

+ 18 - 0
tools/clang/test/CodeGenHLSL/quick-test/obsolete_semantics_ps_2.hlsl

@@ -0,0 +1,18 @@
+// RUN: %dxc -E main -T ps_6_0 %s -Gec | FileCheck %s
+
+// CHECK: COLOR                    0   xyzw        0     NONE   float
+// CHECK: TEXCOORD                 0   xy          1     NONE   float
+// CHECK: SV_Position              0   xyzw        2      POS   float
+// CHECK: SV_Target                1   xyzw        1   TARGET   float   xyzw
+
+struct VOut
+{
+ float4 color : COLOR0;
+ float2 UV    : TEXCOORD0;
+ float4 pos   : VPOS;
+};
+
+float4 main(VOut In) : CoLoR1
+{
+ return float4(0,0,0,0);
+}

+ 15 - 0
tools/clang/test/CodeGenHLSL/quick-test/obsolete_semantics_vs.hlsl

@@ -0,0 +1,15 @@
+// RUN: %dxc -E main -T vs_6_0 %s -Gec | FileCheck %s
+
+// CHECK: COLOR                    0   xyzw        0     NONE   float
+// CHECK: SV_Position              0   xyzw        0      POS   float
+
+struct VSOut
+{
+ float4 a : POSITION;
+};
+
+VSOut main(float4 c : COLOR)
+{
+    VSOut retValue = { {1, 2, 3, 4} };
+    return retValue;
+}