diff --git a/docs/DebugMarkers.md b/docs/DebugMarkers.md index b84024cc5b..da11dfaa96 100644 --- a/docs/DebugMarkers.md +++ b/docs/DebugMarkers.md @@ -17,7 +17,17 @@ for setting up this environment. ## D3D12 -Debug markers are currently unimplemented on D3D12 pending resolution of a licensing issue. +Debug markers on D3D12 are implemented with the [PIX Event Runtime](https://blogs.msdn.microsoft.com/pix/winpixeventruntime/). + +To enable marker functionality, you must: +1. Click the download link on https://www.nuget.org/packages/WinPixEventRuntime +2. Rename the .nupkg file to a .zip extension, then extract its contents. +3. Copy `bin\WinPixEventRuntime.dll` into the same directory as `libdawn_native.dll`. +4. Launch your application. + +You may now call the debug marker APIs mentioned above and see them from your GPU debugging tool. When using your tool, it is supported to both launch your application with the debugger attached, or attach the debugger while your application is running. + +D3D12 debug markers have been tested with [Microsoft PIX](https://blogs.msdn.microsoft.com/pix/download/) and [Intel Graphics Frame Analyzer](https://software.intel.com/en-us/gpa/graphics-frame-analyzer). ## Vulkan diff --git a/src/dawn_native/d3d12/CommandBufferD3D12.cpp b/src/dawn_native/d3d12/CommandBufferD3D12.cpp index f6fd304e82..18e6d1cc48 100644 --- a/src/dawn_native/d3d12/CommandBufferD3D12.cpp +++ b/src/dawn_native/d3d12/CommandBufferD3D12.cpp @@ -24,6 +24,7 @@ #include "dawn_native/d3d12/DescriptorHeapAllocator.h" #include "dawn_native/d3d12/DeviceD3D12.h" #include "dawn_native/d3d12/PipelineLayoutD3D12.h" +#include "dawn_native/d3d12/PlatformFunctions.h" #include "dawn_native/d3d12/RenderPipelineD3D12.h" #include "dawn_native/d3d12/ResourceAllocator.h" #include "dawn_native/d3d12/SamplerD3D12.h" @@ -802,12 +803,40 @@ namespace dawn_native { namespace d3d12 { draw->firstInstance); } break; - case Command::InsertDebugMarker: - case Command::PopDebugGroup: + case Command::InsertDebugMarker: { + InsertDebugMarkerCmd* cmd = mCommands.NextCommand(); + const char* label = mCommands.NextData(cmd->length + 1); + + if (ToBackend(GetDevice())->GetFunctions()->isPIXEventRuntimeLoaded()) { + // PIX color is 1 byte per channel in ARGB format + constexpr uint64_t kPIXBlackColor = 0xff000000; + ToBackend(GetDevice()) + ->GetFunctions() + ->pixSetMarkerOnCommandList(commandList.Get(), kPIXBlackColor, label); + } + } break; + + case Command::PopDebugGroup: { + mCommands.NextCommand(); + + if (ToBackend(GetDevice())->GetFunctions()->isPIXEventRuntimeLoaded()) { + ToBackend(GetDevice()) + ->GetFunctions() + ->pixEndEventOnCommandList(commandList.Get()); + } + } break; + case Command::PushDebugGroup: { - // TODO(brandon1.jones@intel.com): Implement debug markers after PIX licensing - // issue is resolved. - SkipCommand(&mCommands, type); + PushDebugGroupCmd* cmd = mCommands.NextCommand(); + const char* label = mCommands.NextData(cmd->length + 1); + + if (ToBackend(GetDevice())->GetFunctions()->isPIXEventRuntimeLoaded()) { + // PIX color is 1 byte per channel in ARGB format + constexpr uint64_t kPIXBlackColor = 0xff000000; + ToBackend(GetDevice()) + ->GetFunctions() + ->pixBeginEventOnCommandList(commandList.Get(), kPIXBlackColor, label); + } } break; case Command::SetRenderPipeline: { diff --git a/src/dawn_native/d3d12/PlatformFunctions.cpp b/src/dawn_native/d3d12/PlatformFunctions.cpp index 5834a2a931..d9137365f6 100644 --- a/src/dawn_native/d3d12/PlatformFunctions.cpp +++ b/src/dawn_native/d3d12/PlatformFunctions.cpp @@ -27,7 +27,7 @@ namespace dawn_native { namespace d3d12 { DAWN_TRY(LoadD3D12()); DAWN_TRY(LoadDXGI()); DAWN_TRY(LoadD3DCompiler()); - + LoadPIXRuntime(); return {}; } @@ -71,4 +71,18 @@ namespace dawn_native { namespace d3d12 { return {}; } + bool PlatformFunctions::isPIXEventRuntimeLoaded() const { + return mPIXEventRuntimeLib.Valid(); + } + + void PlatformFunctions::LoadPIXRuntime() { + if (!mPIXEventRuntimeLib.Open("WinPixEventRuntime.dll") || + !mPIXEventRuntimeLib.GetProc(&pixBeginEventOnCommandList, + "PIXBeginEventOnCommandList") || + !mPIXEventRuntimeLib.GetProc(&pixEndEventOnCommandList, "PIXEndEventOnCommandList") || + !mPIXEventRuntimeLib.GetProc(&pixSetMarkerOnCommandList, "PIXSetMarkerOnCommandList")) { + mPIXEventRuntimeLib.Close(); + } + } + }} // namespace dawn_native::d3d12 diff --git a/src/dawn_native/d3d12/PlatformFunctions.h b/src/dawn_native/d3d12/PlatformFunctions.h index 710fb84a2b..ec51ba18c5 100644 --- a/src/dawn_native/d3d12/PlatformFunctions.h +++ b/src/dawn_native/d3d12/PlatformFunctions.h @@ -35,6 +35,7 @@ namespace dawn_native { namespace d3d12 { ~PlatformFunctions(); MaybeError LoadFunctions(); + bool isPIXEventRuntimeLoaded() const; // Functions from d3d12.dll PFN_D3D12_CREATE_DEVICE d3d12CreateDevice = nullptr; @@ -60,14 +61,32 @@ namespace dawn_native { namespace d3d12 { // Functions from d3d3compiler.dll pD3DCompile d3dCompile = nullptr; + // Functions from WinPixEventRuntime.dll + using PFN_PIX_END_EVENT_ON_COMMAND_LIST = + HRESULT(WINAPI*)(ID3D12GraphicsCommandList* commandList); + + PFN_PIX_END_EVENT_ON_COMMAND_LIST pixEndEventOnCommandList = nullptr; + + using PFN_PIX_BEGIN_EVENT_ON_COMMAND_LIST = HRESULT( + WINAPI*)(ID3D12GraphicsCommandList* commandList, UINT64 color, _In_ PCSTR formatString); + + PFN_PIX_BEGIN_EVENT_ON_COMMAND_LIST pixBeginEventOnCommandList = nullptr; + + using PFN_SET_MARKER_ON_COMMAND_LIST = HRESULT( + WINAPI*)(ID3D12GraphicsCommandList* commandList, UINT64 color, _In_ PCSTR formatString); + + PFN_SET_MARKER_ON_COMMAND_LIST pixSetMarkerOnCommandList = nullptr; + private: MaybeError LoadD3D12(); MaybeError LoadDXGI(); MaybeError LoadD3DCompiler(); + void LoadPIXRuntime(); DynamicLib mD3D12Lib; DynamicLib mDXGILib; DynamicLib mD3DCompilerLib; + DynamicLib mPIXEventRuntimeLib; }; }} // namespace dawn_native::d3d12