Browse Source

PIX: DxcPixDxilInstructionOffsets should operate on libs (#5046)

Jeff Noyle 2 years ago
parent
commit
67162b4d17
2 changed files with 199 additions and 19 deletions
  1. 22 18
      lib/DxilDia/DxcPixDxilDebugInfo.cpp
  2. 177 1
      tools/clang/unittests/HLSL/PixTest.cpp

+ 22 - 18
lib/DxilDia/DxcPixDxilDebugInfo.cpp

@@ -9,12 +9,15 @@
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
+#include "dxc/DXIL/DxilOperations.h"
+
 #include "dxc/Support/WinIncludes.h"
 
 #include "dxc/Support/exception.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/DebugInfoMetadata.h"
+#include "llvm/IR/Module.h"
 
 #include "DxcPixLiveVariables.h"
 #include "DxcPixDxilDebugInfo.h"
@@ -172,24 +175,25 @@ dxil_debug_info::DxcPixDxilInstructionOffsets::DxcPixDxilInstructionOffsets(
 {
   assert(SourceColumn == 0);
   (void)SourceColumn;
-  auto Fn = pSession->DxilModuleRef().GetEntryFunction();
-  auto &Blocks = Fn->getBasicBlockList();
-  for (auto& CurrentBlock : Blocks) {
-    auto& Is = CurrentBlock.getInstList();
-    for (auto& Inst : Is) {
-      auto & debugLoc = Inst.getDebugLoc();
-      if (debugLoc)
-      {
-        unsigned line = debugLoc.getLine();
-        if (line == SourceLine)
-        {
-          auto file = debugLoc.get()->getFilename();
-          if (CompareFilenames(FileName, file.str().c_str()))
-          {
-            std::uint32_t InstructionNumber;
-            if (pix_dxil::PixDxilInstNum::FromInst(&Inst, &InstructionNumber))
-            {
-              m_offsets.push_back(InstructionNumber);
+  for (llvm::Function &Fn :
+       pSession->DxilModuleRef().GetModule()->functions()) {
+    if (Fn.isDeclaration() || Fn.isIntrinsic() || hlsl::OP::IsDxilOpFunc(&Fn))
+      continue;
+    auto &Blocks = Fn.getBasicBlockList();
+    for (auto &CurrentBlock : Blocks) {
+      auto &Is = CurrentBlock.getInstList();
+      for (auto &Inst : Is) {
+        auto &debugLoc = Inst.getDebugLoc();
+        if (debugLoc) {
+          unsigned line = debugLoc.getLine();
+          if (line == SourceLine) {
+            auto file = debugLoc.get()->getFilename();
+            if (CompareFilenames(FileName, file.str().c_str())) {
+              std::uint32_t InstructionNumber;
+              if (pix_dxil::PixDxilInstNum::FromInst(&Inst,
+                                                     &InstructionNumber)) {
+                m_offsets.push_back(InstructionNumber);
+              }
             }
           }
         }

+ 177 - 1
tools/clang/unittests/HLSL/PixTest.cpp

@@ -229,6 +229,8 @@ public:
   TEST_METHOD(PixTypeManager_SamplersAndResources)
   TEST_METHOD(PixTypeManager_XBoxDiaAssert)
 
+  TEST_METHOD(DxcPixDxilDebugInfo_InstructionOffsets)
+
   TEST_METHOD(VirtualRegisters_InstructionCounts)
   TEST_METHOD(VirtualRegisters_AlignedOffsets)
 
@@ -1803,6 +1805,8 @@ TEST_F(PixTest, PixDebugCompileInfo) {
   VERIFY_ARE_EQUAL(std::wstring(profile), std::wstring(hlslTarget));
 }
 
+static LPCWSTR defaultFilename = L"source.hlsl";
+
 static void CompileAndLogErrors(dxc::DxcDllSupport &dllSupport, LPCSTR pText,
                      LPWSTR pTargetProfile, std::vector<LPCWSTR> &args,
                      _Outptr_ IDxcBlob **ppResult) {
@@ -1813,7 +1817,7 @@ static void CompileAndLogErrors(dxc::DxcDllSupport &dllSupport, LPCSTR pText,
   *ppResult = nullptr;
   VERIFY_SUCCEEDED(dllSupport.CreateInstance(CLSID_DxcCompiler, &pCompiler));
   Utf8ToBlob(dllSupport, pText, &pSource);
-  VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
+  VERIFY_SUCCEEDED(pCompiler->Compile(pSource, defaultFilename, L"main",
                                       pTargetProfile, args.data(), args.size(),
                                       nullptr, 0, nullptr, &pResult));
 
@@ -2143,6 +2147,178 @@ VSOut main( const uint id : SV_OutputControlPointID,
   VERIFY_SUCCEEDED(pDiaDataSource->openSession(&pDiaSession));
 }
 
+std::vector<std::string> SplitAndPreserveEmptyLines(std::string const & str, char delimeter) {
+  std::vector<std::string> lines;
+
+  auto const *p = str.data();
+  auto const *justPastPreviousDelimiter = p;
+  while (p < str.data() + str.length()) {
+    if (*p == delimeter) {
+      lines.emplace_back(justPastPreviousDelimiter, p - justPastPreviousDelimiter);
+      justPastPreviousDelimiter = p + 1;
+      p = justPastPreviousDelimiter;
+    } else {
+      p++;
+    }
+  }
+
+  lines.emplace_back(std::string(justPastPreviousDelimiter,
+                                      p - justPastPreviousDelimiter));
+
+  return lines;
+}
+
+TEST_F(PixTest, DxcPixDxilDebugInfo_InstructionOffsets) {
+
+  if (m_ver.SkipDxilVersion(1, 5))
+    return;
+
+  const char *hlsl = R"(RaytracingAccelerationStructure Scene : register(t0, space0);
+RWTexture2D<float4> RenderTarget : register(u0);
+
+struct SceneConstantBuffer
+{
+    float4x4 projectionToWorld;
+    float4 cameraPosition;
+    float4 lightPosition;
+    float4 lightAmbientColor;
+    float4 lightDiffuseColor;
+};
+
+ConstantBuffer<SceneConstantBuffer> g_sceneCB : register(b0);
+
+struct RayPayload
+{
+    float4 color;
+};
+
+inline void GenerateCameraRay(uint2 index, out float3 origin, out float3 direction)
+{
+    float2 xy = index + 0.5f; // center in the middle of the pixel.
+    float2 screenPos = xy;// / DispatchRaysDimensions().xy * 2.0 - 1.0;
+
+    // Invert Y for DirectX-style coordinates.
+    screenPos.y = -screenPos.y;
+
+    // Unproject the pixel coordinate into a ray.
+    float4 world = /*mul(*/float4(screenPos, 0, 1)/*, g_sceneCB.projectionToWorld)*/;
+
+    //world.xyz /= world.w;
+    origin = world.xyz; //g_sceneCB.cameraPosition.xyz;
+    direction = float3(1,0,0);//normalize(world.xyz - origin);
+}
+
+void RaygenCommon()
+{
+    float3 rayDir;
+    float3 origin;
+    
+    // Generate a ray for a camera pixel corresponding to an index from the dispatched 2D grid.
+    GenerateCameraRay(DispatchRaysIndex().xy, origin, rayDir);
+
+    // Trace the ray.
+    // Set the ray's extents.
+    RayDesc ray;
+    ray.Origin = origin;
+    ray.Direction = rayDir;
+    // Set TMin to a non-zero small value to avoid aliasing issues due to floating - point errors.
+    // TMin should be kept small to prevent missing geometry at close contact areas.
+    ray.TMin = 0.001;
+    ray.TMax = 10000.0;
+    RayPayload payload = { float4(0, 0, 0, 0) };
+    TraceRay(Scene, RAY_FLAG_CULL_BACK_FACING_TRIANGLES, ~0, 0, 1, 0, ray, payload);
+
+    // Write the raytraced color to the output texture.
+   // RenderTarget[DispatchRaysIndex().xy] = payload.color;
+}
+
+[shader("raygeneration")]
+void Raygen()
+{
+    RaygenCommon();
+}
+
+typedef BuiltInTriangleIntersectionAttributes MyAttributes;
+
+[shader("closesthit")]
+void InnerClosestHitShader(inout RayPayload payload, in MyAttributes attr)
+{
+    payload.color = float4(0,1,0,0);
+}
+
+
+[shader("miss")]
+void MyMissShader(inout RayPayload payload)
+{
+    payload.color = float4(1, 0, 0, 0);
+})";
+
+  auto lines = SplitAndPreserveEmptyLines(std::string(hlsl), '\n');
+  DWORD countOfSourceLines = static_cast<DWORD>(lines.size());
+
+  CComPtr<IDiaDataSource> pDiaDataSource;
+  CompileAndRunAnnotationAndLoadDiaSource(m_dllSupport, hlsl, L"lib_6_6",
+                                          &pDiaDataSource);
+
+  CComPtr<IDiaSession> session;
+  VERIFY_SUCCEEDED(pDiaDataSource->openSession(&session));
+
+  CComPtr<IDxcPixDxilDebugInfoFactory> Factory;
+  VERIFY_SUCCEEDED(session->QueryInterface(IID_PPV_ARGS(&Factory)));
+
+  CComPtr<IDxcPixDxilDebugInfo> dxilDebugger;
+  VERIFY_SUCCEEDED(Factory->NewDxcPixDxilDebugInfo(&dxilDebugger));
+
+  // Quick crash test for wrong filename:
+  CComPtr<IDxcPixDxilInstructionOffsets> garbageOffsets;
+  dxilDebugger->InstructionOffsetsFromSourceLocation(L"garbage", 0, 0,
+                                                     &garbageOffsets);
+
+  // Since the API offers both source-from-instruction and
+  // instruction-from-source, we'll compare them against each other:
+  for (size_t line = 0; line < lines.size(); ++line) {
+
+    auto lineNumber = static_cast<DWORD>(line);
+
+    constexpr DWORD sourceLocationReaderOnlySupportsColumnZero = 0;
+    CComPtr<IDxcPixDxilInstructionOffsets> offsets;
+    dxilDebugger->InstructionOffsetsFromSourceLocation(
+        defaultFilename, lineNumber, sourceLocationReaderOnlySupportsColumnZero,
+        &offsets);
+
+    auto offsetCount = offsets->GetCount();
+    for (DWORD offsetOrdinal = 0; offsetOrdinal < offsetCount;
+         ++offsetOrdinal) {
+
+      DWORD instructionOffsetFromSource =
+          offsets->GetOffsetByIndex(offsetOrdinal);
+
+      CComPtr<IDxcPixDxilSourceLocations> sourceLocations;
+      VERIFY_SUCCEEDED(dxilDebugger->SourceLocationsFromInstructionOffset(
+          instructionOffsetFromSource, &sourceLocations));
+
+      auto count = sourceLocations->GetCount();
+      for (DWORD sourceLocationOrdinal = 0; sourceLocationOrdinal < count;
+           ++sourceLocationOrdinal) {
+        DWORD lineNumber =
+            sourceLocations->GetLineNumberByIndex(sourceLocationOrdinal);
+        DWORD column = sourceLocations->GetColumnByIndex(sourceLocationOrdinal);
+        CComBSTR filename;
+        VERIFY_SUCCEEDED(sourceLocations->GetFileNameByIndex(
+            sourceLocationOrdinal, &filename));
+
+        VERIFY_IS_TRUE(lineNumber < countOfSourceLines);
+
+        constexpr DWORD lineNumbersAndColumnsStartAtOne = 1;
+        VERIFY_IS_TRUE(
+            column - lineNumbersAndColumnsStartAtOne  <=
+            static_cast<DWORD>(lines.at(lineNumber - lineNumbersAndColumnsStartAtOne).size()));
+        VERIFY_IS_TRUE(0 == wcscmp(filename, defaultFilename));
+      }
+    }
+  }
+}
+
 CComPtr<IDxcBlob> PixTest::RunShaderAccessTrackingPass(IDxcBlob *blob) {
   CComPtr<IDxcOptimizer> pOptimizer;
   VERIFY_SUCCEEDED(