Browse Source

Merged PR 109: Enable Dxil Op validation for library functions.

Enable Dxil Op validation for library functions.
Tex Riddell 7 years ago
parent
commit
0f166b8c24

+ 3 - 1
lib/HLSL/DxilShaderModel.cpp

@@ -205,7 +205,9 @@ void ShaderModel::GetMinValidatorVersion(unsigned &ValMajor, unsigned &ValMinor)
 }
 
 static const char *ShaderModelKindNames[] = {
-    "ps", "vs", "gs", "hs", "ds", "cs", "lib", "invalid",
+    "ps", "vs", "gs", "hs", "ds", "cs", "lib",
+    "raygeneration", "intersection", "anyhit", "closesthit", "miss", "callable",
+    "invalid",
 };
 
 std::string ShaderModel::GetKindName() const {

+ 57 - 35
lib/HLSL/DxilValidation.cpp

@@ -751,85 +751,87 @@ struct ValidationContext {
 };
 
 static bool ValidateOpcodeInProfile(DXIL::OpCode opcode,
-                                    const ShaderModel *pSM) {
+                                    DXIL::ShaderKind SK,
+                                    unsigned major,
+                                    unsigned minor) {
   unsigned op = (unsigned)opcode;
   /* <py::lines('VALOPCODESM-TEXT')>hctdb_instrhelp.get_valopcode_sm_text()</py>*/
   // VALOPCODESM-TEXT:BEGIN
   // Instructions: ThreadId=93, GroupId=94, ThreadIdInGroup=95,
   // FlattenedThreadIdInGroup=96
   if ((93 <= op && op <= 96))
-    return (pSM->IsCS());
+    return (SK == DXIL::ShaderKind::Compute);
   // Instructions: DomainLocation=105
   if (op == 105)
-    return (pSM->IsDS());
+    return (SK == DXIL::ShaderKind::Domain);
   // Instructions: LoadOutputControlPoint=103, LoadPatchConstant=104
   if ((103 <= op && op <= 104))
-    return (pSM->IsDS() || pSM->IsHS());
+    return (SK == DXIL::ShaderKind::Domain || SK == DXIL::ShaderKind::Hull);
   // Instructions: EmitStream=97, CutStream=98, EmitThenCutStream=99,
   // GSInstanceID=100
   if ((97 <= op && op <= 100))
-    return (pSM->IsGS());
+    return (SK == DXIL::ShaderKind::Geometry);
   // Instructions: PrimitiveID=108
   if (op == 108)
-    return (pSM->IsGS() || pSM->IsDS() || pSM->IsHS());
+    return (SK == DXIL::ShaderKind::Geometry || SK == DXIL::ShaderKind::Domain || SK == DXIL::ShaderKind::Hull);
   // Instructions: StorePatchConstant=106, OutputControlPointID=107
   if ((106 <= op && op <= 107))
-    return (pSM->IsHS());
+    return (SK == DXIL::ShaderKind::Hull);
   // Instructions: Sample=60, SampleBias=61, SampleCmp=64, CalculateLOD=81,
   // DerivCoarseX=83, DerivCoarseY=84, DerivFineX=85, DerivFineY=86
   if ((60 <= op && op <= 61) || op == 64 || op == 81 || (83 <= op && op <= 86))
-    return (pSM->IsLib() || pSM->IsPS());
+    return (SK == DXIL::ShaderKind::Library || SK == DXIL::ShaderKind::Pixel);
   // Instructions: RenderTargetGetSamplePosition=76,
   // RenderTargetGetSampleCount=77, Discard=82, EvalSnapped=87,
   // EvalSampleIndex=88, EvalCentroid=89, SampleIndex=90, Coverage=91,
   // InnerCoverage=92
   if ((76 <= op && op <= 77) || op == 82 || (87 <= op && op <= 92))
-    return (pSM->IsPS());
+    return (SK == DXIL::ShaderKind::Pixel);
   // Instructions: AttributeAtVertex=137
   if (op == 137)
-    return (pSM->GetMajor() > 6 || (pSM->GetMajor() == 6 && pSM->GetMinor() >= 1))
-        && (pSM->IsPS());
+    return (major > 6 || (major == 6 && minor >= 1))
+        && (SK == DXIL::ShaderKind::Pixel);
   // Instructions: ViewID=138
   if (op == 138)
-    return (pSM->GetMajor() > 6 || (pSM->GetMajor() == 6 && pSM->GetMinor() >= 1))
-        && (pSM->IsVS() || pSM->IsHS() || pSM->IsDS() || pSM->IsGS() || pSM->IsPS());
+    return (major > 6 || (major == 6 && minor >= 1))
+        && (SK == DXIL::ShaderKind::Vertex || SK == DXIL::ShaderKind::Hull || SK == DXIL::ShaderKind::Domain || SK == DXIL::ShaderKind::Geometry || SK == DXIL::ShaderKind::Pixel);
   // Instructions: RawBufferLoad=139, RawBufferStore=140
   if ((139 <= op && op <= 140))
-    return (pSM->GetMajor() > 6 || (pSM->GetMajor() == 6 && pSM->GetMinor() >= 2));
+    return (major > 6 || (major == 6 && minor >= 2));
   // Instructions: CreateHandleForLib=160
   if (op == 160)
-    return (pSM->GetMajor() > 6 || (pSM->GetMajor() == 6 && pSM->GetMinor() >= 3));
+    return (major > 6 || (major == 6 && minor >= 3));
   // Instructions: IgnoreHit=155, AcceptHitAndEndSearch=156
   if ((155 <= op && op <= 156))
-    return (pSM->GetMajor() > 6 || (pSM->GetMajor() == 6 && pSM->GetMinor() >= 3))
-        && (pSM->GetKind() == DXIL::ShaderKind::AnyHit);
+    return (major > 6 || (major == 6 && minor >= 3))
+        && (SK == DXIL::ShaderKind::AnyHit);
   // Instructions: CallShader=159
   if (op == 159)
-    return (pSM->GetMajor() > 6 || (pSM->GetMajor() == 6 && pSM->GetMinor() >= 3))
-        && (pSM->IsLib() || pSM->GetKind() == DXIL::ShaderKind::ClosestHit || pSM->GetKind() == DXIL::ShaderKind::RayGeneration || pSM->GetKind() == DXIL::ShaderKind::Miss || pSM->GetKind() == DXIL::ShaderKind::Callable);
+    return (major > 6 || (major == 6 && minor >= 3))
+        && (SK == DXIL::ShaderKind::Library || SK == DXIL::ShaderKind::ClosestHit || SK == DXIL::ShaderKind::RayGeneration || SK == DXIL::ShaderKind::Miss || SK == DXIL::ShaderKind::Callable);
   // Instructions: ReportHit=158
   if (op == 158)
-    return (pSM->GetMajor() > 6 || (pSM->GetMajor() == 6 && pSM->GetMinor() >= 3))
-        && (pSM->IsLib() || pSM->GetKind() == DXIL::ShaderKind::Intersection);
+    return (major > 6 || (major == 6 && minor >= 3))
+        && (SK == DXIL::ShaderKind::Library || SK == DXIL::ShaderKind::Intersection);
   // Instructions: InstanceID=141, InstanceIndex=142, HitKind=143,
   // ObjectRayOrigin=149, ObjectRayDirection=150, ObjectToWorld=151,
   // WorldToObject=152, PrimitiveIndex=161
   if ((141 <= op && op <= 143) || (149 <= op && op <= 152) || op == 161)
-    return (pSM->GetMajor() > 6 || (pSM->GetMajor() == 6 && pSM->GetMinor() >= 3))
-        && (pSM->IsLib() || pSM->GetKind() == DXIL::ShaderKind::Intersection || pSM->GetKind() == DXIL::ShaderKind::AnyHit || pSM->GetKind() == DXIL::ShaderKind::ClosestHit);
+    return (major > 6 || (major == 6 && minor >= 3))
+        && (SK == DXIL::ShaderKind::Library || SK == DXIL::ShaderKind::Intersection || SK == DXIL::ShaderKind::AnyHit || SK == DXIL::ShaderKind::ClosestHit);
   // Instructions: RayFlags=144, WorldRayOrigin=147, WorldRayDirection=148,
   // RayTMin=153, RayTCurrent=154
   if (op == 144 || (147 <= op && op <= 148) || (153 <= op && op <= 154))
-    return (pSM->GetMajor() > 6 || (pSM->GetMajor() == 6 && pSM->GetMinor() >= 3))
-        && (pSM->IsLib() || pSM->GetKind() == DXIL::ShaderKind::Intersection || pSM->GetKind() == DXIL::ShaderKind::AnyHit || pSM->GetKind() == DXIL::ShaderKind::ClosestHit || pSM->GetKind() == DXIL::ShaderKind::Miss);
+    return (major > 6 || (major == 6 && minor >= 3))
+        && (SK == DXIL::ShaderKind::Library || SK == DXIL::ShaderKind::Intersection || SK == DXIL::ShaderKind::AnyHit || SK == DXIL::ShaderKind::ClosestHit || SK == DXIL::ShaderKind::Miss);
   // Instructions: TraceRay=157
   if (op == 157)
-    return (pSM->GetMajor() > 6 || (pSM->GetMajor() == 6 && pSM->GetMinor() >= 3))
-        && (pSM->IsLib() || pSM->GetKind() == DXIL::ShaderKind::RayGeneration || pSM->GetKind() == DXIL::ShaderKind::ClosestHit || pSM->GetKind() == DXIL::ShaderKind::Miss);
+    return (major > 6 || (major == 6 && minor >= 3))
+        && (SK == DXIL::ShaderKind::Library || SK == DXIL::ShaderKind::RayGeneration || SK == DXIL::ShaderKind::ClosestHit || SK == DXIL::ShaderKind::Miss);
   // Instructions: DispatchRaysIndex=145, DispatchRaysDimensions=146
   if ((145 <= op && op <= 146))
-    return (pSM->GetMajor() > 6 || (pSM->GetMajor() == 6 && pSM->GetMinor() >= 3))
-        && (pSM->IsLib() || pSM->GetKind() == DXIL::ShaderKind::RayGeneration || pSM->GetKind() == DXIL::ShaderKind::Intersection || pSM->GetKind() == DXIL::ShaderKind::AnyHit || pSM->GetKind() == DXIL::ShaderKind::ClosestHit || pSM->GetKind() == DXIL::ShaderKind::Miss || pSM->GetKind() == DXIL::ShaderKind::Callable);
+    return (major > 6 || (major == 6 && minor >= 3))
+        && (SK == DXIL::ShaderKind::Library || SK == DXIL::ShaderKind::RayGeneration || SK == DXIL::ShaderKind::Intersection || SK == DXIL::ShaderKind::AnyHit || SK == DXIL::ShaderKind::ClosestHit || SK == DXIL::ShaderKind::Miss || SK == DXIL::ShaderKind::Callable);
   return true;
   // VALOPCODESM-TEXT:END
 }
@@ -2454,12 +2456,32 @@ static void ValidateExternalFunction(Function *F, ValidationContext &ValCtx) {
       continue;
     }
 
-    if (!ValCtx.isLibProfile && !ValidateOpcodeInProfile(dxilOpcode, pSM)) {
-      // Opcode not available in profile.
-      ValCtx.EmitInstrFormatError(CI, ValidationRule::SmOpcode,
-                                  {hlslOP->GetOpCodeName(dxilOpcode),
-                                   pSM->GetName()});
-      continue;
+    unsigned major = pSM->GetMajor();
+    unsigned minor = pSM->GetMinor();
+    if (ValCtx.isLibProfile) {
+      Function *callingFunction = CI->getParent()->getParent();
+      DXIL::ShaderKind SK = DXIL::ShaderKind::Library;
+      if (ValCtx.DxilMod.HasDxilFunctionProps(callingFunction))
+        SK = ValCtx.DxilMod.GetDxilFunctionProps(callingFunction).shaderKind;
+      else if (ValCtx.DxilMod.IsPatchConstantShader(callingFunction))
+        SK = DXIL::ShaderKind::Hull;
+      if (!ValidateOpcodeInProfile(dxilOpcode, SK, major, minor)) {
+        // Opcode not available in profile.
+        // produces: "lib_6_3(ps)", or "lib_6_3(anyhit)" for shader types
+        // Or: "lib_6_3(lib)" for library function
+        std::string shaderModel = pSM->GetName();
+        shaderModel += "(" + ShaderModel::GetKindName(SK) + ")";
+        ValCtx.EmitInstrFormatError(CI, ValidationRule::SmOpcode,
+          { hlslOP->GetOpCodeName(dxilOpcode), shaderModel });
+        continue;
+      }
+    } else {
+      if (!ValidateOpcodeInProfile(dxilOpcode, pSM->GetKind(), major, minor)) {
+        // Opcode not available in profile.
+        ValCtx.EmitInstrFormatError(CI, ValidationRule::SmOpcode,
+          { hlslOP->GetOpCodeName(dxilOpcode), pSM->GetName() });
+        continue;
+      }
     }
 
     // Check more detail.

+ 4 - 2
tools/clang/test/CodeGenHLSL/quick-test/raytracing_accept_ignore_hit_fail_lib.hlsl

@@ -1,7 +1,9 @@
 // RUN: %dxc -T lib_6_3 -auto-binding-space 11 %s | FileCheck %s
 
-// TODO: verify failure for exported library function and flip the CHECK below
-// CHECK: define void @"\01?libfunc
+// verify failure for exported library function
+// CHECK: Opcode IgnoreHit not valid in shader model lib_6_3(lib)
+// CHECK: Opcode AcceptHitAndEndSearch not valid in shader model lib_6_3(lib)
+
 
 struct Payload {
   float foo;

+ 2 - 2
tools/clang/unittests/HLSL/DxilContainerTest.cpp

@@ -879,8 +879,8 @@ TEST_F(DxilContainerTest, CompileWhenOkThenCheckRDAT2) {
       "register(u0); Texture2D<float> ThreeTextures[3] : register(t0); "
       "float function1();"
       "[shader(\"raygeneration\")] void RayGenMain() { Uav[0] = "
-      "ThreeTextures[0].Sample(Sampler, float2(0, 0)) + "
-      "ThreeTextures[2].Sample(Sampler, float2(0, 0)) + function1(); }";
+      "ThreeTextures[0].SampleLevel(Sampler, float2(0, 0), 0) + "
+      "ThreeTextures[2].SampleLevel(Sampler, float2(0, 0), 0) + function1(); }";
   CComPtr<IDxcCompiler> pCompiler;
   CComPtr<IDxcBlobEncoding> pSource;
   CComPtr<IDxcBlob> pProgram;

+ 14 - 14
utils/hct/hctdb_instrhelp.py

@@ -983,19 +983,19 @@ def get_min_sm_and_mask_text():
     return code
 
 check_pSM_for_shader_stage = {
-    'vertex': 'pSM->IsVS()',
-    'pixel': 'pSM->IsPS()',
-    'geometry': 'pSM->IsGS()',
-    'compute': 'pSM->IsCS()',
-    'hull': 'pSM->IsHS()',
-    'domain': 'pSM->IsDS()',
-    'library': 'pSM->IsLib()',
-    'raygeneration': 'pSM->GetKind() == DXIL::ShaderKind::RayGeneration',
-    'intersection': 'pSM->GetKind() == DXIL::ShaderKind::Intersection',
-    'anyhit': 'pSM->GetKind() == DXIL::ShaderKind::AnyHit',
-    'closesthit': 'pSM->GetKind() == DXIL::ShaderKind::ClosestHit',
-    'miss': 'pSM->GetKind() == DXIL::ShaderKind::Miss',
-    'callable': 'pSM->GetKind() == DXIL::ShaderKind::Callable',
+    'vertex': 'SK == DXIL::ShaderKind::Vertex',
+    'pixel': 'SK == DXIL::ShaderKind::Pixel',
+    'geometry': 'SK == DXIL::ShaderKind::Geometry',
+    'compute': 'SK == DXIL::ShaderKind::Compute',
+    'hull': 'SK == DXIL::ShaderKind::Hull',
+    'domain': 'SK == DXIL::ShaderKind::Domain',
+    'library': 'SK == DXIL::ShaderKind::Library',
+    'raygeneration': 'SK == DXIL::ShaderKind::RayGeneration',
+    'intersection': 'SK == DXIL::ShaderKind::Intersection',
+    'anyhit': 'SK == DXIL::ShaderKind::AnyHit',
+    'closesthit': 'SK == DXIL::ShaderKind::ClosestHit',
+    'miss': 'SK == DXIL::ShaderKind::Miss',
+    'callable': 'SK == DXIL::ShaderKind::Callable',
 }
 
 def get_valopcode_sm_text():
@@ -1015,7 +1015,7 @@ def get_valopcode_sm_text():
 
         model_cond = stage_cond = None
         if last_model != (6,0):
-            model_cond = "pSM->GetMajor() > %d || (pSM->GetMajor() == %d && pSM->GetMinor() >= %d)" % (
+            model_cond = "major > %d || (major == %d && minor >= %d)" % (
                 last_model[0], last_model[0], last_model[1])
         if last_stage:
             stage_cond = ' || '.join([check_pSM_for_shader_stage[c] for c in last_stage])