@@ -229,6 +229,8 @@ class PixTest {
229229 TEST_METHOD (PixTypeManager_SamplersAndResources)
230230 TEST_METHOD (PixTypeManager_XBoxDiaAssert)
231231
232+ TEST_METHOD (DxcPixDxilDebugInfo_InstructionOffsets)
233+
232234 TEST_METHOD (VirtualRegisters_InstructionCounts)
233235 TEST_METHOD (VirtualRegisters_AlignedOffsets)
234236
@@ -1803,6 +1805,8 @@ TEST_F(PixTest, PixDebugCompileInfo) {
18031805 VERIFY_ARE_EQUAL (std::wstring (profile), std::wstring (hlslTarget));
18041806}
18051807
1808+ static LPCWSTR defaultFilename = L" source.hlsl" ;
1809+
18061810static void CompileAndLogErrors (dxc::DxcDllSupport &dllSupport, LPCSTR pText,
18071811 LPWSTR pTargetProfile, std::vector<LPCWSTR> &args,
18081812 _Outptr_ IDxcBlob **ppResult) {
@@ -1813,7 +1817,7 @@ static void CompileAndLogErrors(dxc::DxcDllSupport &dllSupport, LPCSTR pText,
18131817 *ppResult = nullptr ;
18141818 VERIFY_SUCCEEDED (dllSupport.CreateInstance (CLSID_DxcCompiler, &pCompiler));
18151819 Utf8ToBlob (dllSupport, pText, &pSource);
1816- VERIFY_SUCCEEDED (pCompiler->Compile (pSource, L" source.hlsl " , L" main" ,
1820+ VERIFY_SUCCEEDED (pCompiler->Compile (pSource, defaultFilename , L" main" ,
18171821 pTargetProfile, args.data (), args.size (),
18181822 nullptr , 0 , nullptr , &pResult));
18191823
@@ -2143,6 +2147,178 @@ VSOut main( const uint id : SV_OutputControlPointID,
21432147 VERIFY_SUCCEEDED (pDiaDataSource->openSession (&pDiaSession));
21442148}
21452149
2150+ std::vector<std::string> SplitAndPreserveEmptyLines (std::string const & str, char delimeter) {
2151+ std::vector<std::string> lines;
2152+
2153+ auto const *p = str.data ();
2154+ auto const *justPastPreviousDelimiter = p;
2155+ while (p < str.data () + str.length ()) {
2156+ if (*p == delimeter) {
2157+ lines.emplace_back (justPastPreviousDelimiter, p - justPastPreviousDelimiter);
2158+ justPastPreviousDelimiter = p + 1 ;
2159+ p = justPastPreviousDelimiter;
2160+ } else {
2161+ p++;
2162+ }
2163+ }
2164+
2165+ lines.emplace_back (std::string (justPastPreviousDelimiter,
2166+ p - justPastPreviousDelimiter));
2167+
2168+ return lines;
2169+ }
2170+
2171+ TEST_F (PixTest, DxcPixDxilDebugInfo_InstructionOffsets) {
2172+
2173+ if (m_ver.SkipDxilVersion (1 , 5 ))
2174+ return ;
2175+
2176+ const char *hlsl = R"( RaytracingAccelerationStructure Scene : register(t0, space0);
2177+ RWTexture2D<float4> RenderTarget : register(u0);
2178+
2179+ struct SceneConstantBuffer
2180+ {
2181+ float4x4 projectionToWorld;
2182+ float4 cameraPosition;
2183+ float4 lightPosition;
2184+ float4 lightAmbientColor;
2185+ float4 lightDiffuseColor;
2186+ };
2187+
2188+ ConstantBuffer<SceneConstantBuffer> g_sceneCB : register(b0);
2189+
2190+ struct RayPayload
2191+ {
2192+ float4 color;
2193+ };
2194+
2195+ inline void GenerateCameraRay(uint2 index, out float3 origin, out float3 direction)
2196+ {
2197+ float2 xy = index + 0.5f; // center in the middle of the pixel.
2198+ float2 screenPos = xy;// / DispatchRaysDimensions().xy * 2.0 - 1.0;
2199+
2200+ // Invert Y for DirectX-style coordinates.
2201+ screenPos.y = -screenPos.y;
2202+
2203+ // Unproject the pixel coordinate into a ray.
2204+ float4 world = /*mul(*/float4(screenPos, 0, 1)/*, g_sceneCB.projectionToWorld)*/;
2205+
2206+ //world.xyz /= world.w;
2207+ origin = world.xyz; //g_sceneCB.cameraPosition.xyz;
2208+ direction = float3(1,0,0);//normalize(world.xyz - origin);
2209+ }
2210+
2211+ void RaygenCommon()
2212+ {
2213+ float3 rayDir;
2214+ float3 origin;
2215+
2216+ // Generate a ray for a camera pixel corresponding to an index from the dispatched 2D grid.
2217+ GenerateCameraRay(DispatchRaysIndex().xy, origin, rayDir);
2218+
2219+ // Trace the ray.
2220+ // Set the ray's extents.
2221+ RayDesc ray;
2222+ ray.Origin = origin;
2223+ ray.Direction = rayDir;
2224+ // Set TMin to a non-zero small value to avoid aliasing issues due to floating - point errors.
2225+ // TMin should be kept small to prevent missing geometry at close contact areas.
2226+ ray.TMin = 0.001;
2227+ ray.TMax = 10000.0;
2228+ RayPayload payload = { float4(0, 0, 0, 0) };
2229+ TraceRay(Scene, RAY_FLAG_CULL_BACK_FACING_TRIANGLES, ~0, 0, 1, 0, ray, payload);
2230+
2231+ // Write the raytraced color to the output texture.
2232+ // RenderTarget[DispatchRaysIndex().xy] = payload.color;
2233+ }
2234+
2235+ [shader("raygeneration")]
2236+ void Raygen()
2237+ {
2238+ RaygenCommon();
2239+ }
2240+
2241+ typedef BuiltInTriangleIntersectionAttributes MyAttributes;
2242+
2243+ [shader("closesthit")]
2244+ void InnerClosestHitShader(inout RayPayload payload, in MyAttributes attr)
2245+ {
2246+ payload.color = float4(0,1,0,0);
2247+ }
2248+
2249+
2250+ [shader("miss")]
2251+ void MyMissShader(inout RayPayload payload)
2252+ {
2253+ payload.color = float4(1, 0, 0, 0);
2254+ })" ;
2255+
2256+ auto lines = SplitAndPreserveEmptyLines (std::string (hlsl), ' \n ' );
2257+ DWORD countOfSourceLines = static_cast <DWORD>(lines.size ());
2258+
2259+ CComPtr<IDiaDataSource> pDiaDataSource;
2260+ CompileAndRunAnnotationAndLoadDiaSource (m_dllSupport, hlsl, L" lib_6_6" ,
2261+ &pDiaDataSource);
2262+
2263+ CComPtr<IDiaSession> session;
2264+ VERIFY_SUCCEEDED (pDiaDataSource->openSession (&session));
2265+
2266+ CComPtr<IDxcPixDxilDebugInfoFactory> Factory;
2267+ VERIFY_SUCCEEDED (session->QueryInterface (IID_PPV_ARGS (&Factory)));
2268+
2269+ CComPtr<IDxcPixDxilDebugInfo> dxilDebugger;
2270+ VERIFY_SUCCEEDED (Factory->NewDxcPixDxilDebugInfo (&dxilDebugger));
2271+
2272+ // Quick crash test for wrong filename:
2273+ CComPtr<IDxcPixDxilInstructionOffsets> garbageOffsets;
2274+ dxilDebugger->InstructionOffsetsFromSourceLocation (L" garbage" , 0 , 0 ,
2275+ &garbageOffsets);
2276+
2277+ // Since the API offers both source-from-instruction and
2278+ // instruction-from-source, we'll compare them against each other:
2279+ for (size_t line = 0 ; line < lines.size (); ++line) {
2280+
2281+ auto lineNumber = static_cast <DWORD>(line);
2282+
2283+ constexpr DWORD sourceLocationReaderOnlySupportsColumnZero = 0 ;
2284+ CComPtr<IDxcPixDxilInstructionOffsets> offsets;
2285+ dxilDebugger->InstructionOffsetsFromSourceLocation (
2286+ defaultFilename, lineNumber, sourceLocationReaderOnlySupportsColumnZero,
2287+ &offsets);
2288+
2289+ auto offsetCount = offsets->GetCount ();
2290+ for (DWORD offsetOrdinal = 0 ; offsetOrdinal < offsetCount;
2291+ ++offsetOrdinal) {
2292+
2293+ DWORD instructionOffsetFromSource =
2294+ offsets->GetOffsetByIndex (offsetOrdinal);
2295+
2296+ CComPtr<IDxcPixDxilSourceLocations> sourceLocations;
2297+ VERIFY_SUCCEEDED (dxilDebugger->SourceLocationsFromInstructionOffset (
2298+ instructionOffsetFromSource, &sourceLocations));
2299+
2300+ auto count = sourceLocations->GetCount ();
2301+ for (DWORD sourceLocationOrdinal = 0 ; sourceLocationOrdinal < count;
2302+ ++sourceLocationOrdinal) {
2303+ DWORD lineNumber =
2304+ sourceLocations->GetLineNumberByIndex (sourceLocationOrdinal);
2305+ DWORD column = sourceLocations->GetColumnByIndex (sourceLocationOrdinal);
2306+ CComBSTR filename;
2307+ VERIFY_SUCCEEDED (sourceLocations->GetFileNameByIndex (
2308+ sourceLocationOrdinal, &filename));
2309+
2310+ VERIFY_IS_TRUE (lineNumber < countOfSourceLines);
2311+
2312+ constexpr DWORD lineNumbersAndColumnsStartAtOne = 1 ;
2313+ VERIFY_IS_TRUE (
2314+ column - lineNumbersAndColumnsStartAtOne <=
2315+ static_cast <DWORD>(lines.at (lineNumber - lineNumbersAndColumnsStartAtOne).size ()));
2316+ VERIFY_IS_TRUE (0 == wcscmp (filename, defaultFilename));
2317+ }
2318+ }
2319+ }
2320+ }
2321+
21462322CComPtr<IDxcBlob> PixTest::RunShaderAccessTrackingPass (IDxcBlob *blob) {
21472323 CComPtr<IDxcOptimizer> pOptimizer;
21482324 VERIFY_SUCCEEDED (
0 commit comments