{"id":6094,"date":"2023-03-30T12:08:57","date_gmt":"2023-03-30T19:08:57","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/pix\/?p=6094"},"modified":"2023-03-30T12:08:57","modified_gmt":"2023-03-30T19:08:57","slug":"pix-and-id3d12manualwritetrackingresource","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/pix\/pix-and-id3d12manualwritetrackingresource\/","title":{"rendered":"PIX and ID3D12ManualWriteTrackingResource\u00a0"},"content":{"rendered":"<h3>Summary<\/h3>\n<p><span data-contrast=\"auto\">If you\u2019re using GPU_UPLOAD heaps and you are experiencing capture-time performance issues when you launch your application via PIX (e.g. your game\u2019s framerate drops) then read on to learn how ID3D12ManualWriteTrackingResource might help you.<\/span><\/p>\n<p>&nbsp;<\/p>\n<h3>Background<\/h3>\n<p><span data-contrast=\"auto\">When taking a GPU Capture, PIX (and other graphics debugging tools) often use <\/span><a href=\"https:\/\/learn.microsoft.com\/en-us\/windows\/win32\/api\/d3d12\/ne-d3d12-d3d12_heap_flags\"><span data-contrast=\"none\">WRITE_WATCH<\/span><\/a><span data-contrast=\"auto\"> to automatically detect modifications to CPU-writeable (a.k.a. \u201cmappable\u201d) resources such as UPLOAD or GPU_UPLOAD resources. This was a reliable solution, but it poses a problem for GPU_UPLOAD heaps because current versions of Windows* don\u2019t allow WRITE_WATCH resources\/heaps to live in discrete video memory. <\/span><span data-ccp-props=\"{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<span style=\"font-size: 8pt;\"><em>(*as-of March 2023)<\/em><\/span><\/span><\/p>\n<p><span data-contrast=\"auto\">This means that GPU_UPLOAD resources\/heaps are forced into system memory when WRITE_WATCH is turned on, which may cause a performance loss in your game when it\u2019s running under PIX capture.\u00a0<\/span><span data-ccp-props=\"{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"auto\">This issue affects all retail versions of Windows today, but it is fixed in the latest <\/span><a href=\"https:\/\/blogs.windows.com\/windows-insider\/2023\/02\/21\/releasing-windows-11-build-22621-1343-to-the-release-preview-channel\/\"><span data-contrast=\"none\">Windows 11 Insider build<\/span><\/a><span data-contrast=\"auto\">. Note that this issue does <\/span><i><span data-contrast=\"auto\">not<\/span><\/i><span data-contrast=\"auto\"> affect PIX playback performance or the correctness of performance data in PIX.<\/span><span data-ccp-props=\"{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"auto\">Applications can avoid these issues by using ID3D12ManualWriteTrackingResource.<\/span><span data-ccp-props=\"{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<p>&nbsp;<\/p>\n<h3>Introducing ID3D12ManualWriteTrackingResource<\/h3>\n<p><span data-contrast=\"auto\">The PIX and D3D12 teams have collaborated to define a manual write tracking API: ID3D12ManualWriteTrackingResource, defined in d3d12sdklayers.h. This API allows applications or middleware components to turn off WRITE_WATCH tracking for a particular mappable resource or heap, on the condition that the application or component manually notifies PIX every time the resource\/heap is modified via the CPU.<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<p>&nbsp;<\/p>\n<h3>How to use ID3D12ManualWriteTrackingResource<\/h3>\n<p><span data-contrast=\"auto\">Firstly you must check if manual write tracking is supported by calling ID3D12Device::CheckFeatureSupport:<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">\u00a0\u00a0\u00a0 bool IsManualWriteTrackingSupported(ID3D12Device* device)\u00a0\r\n\u00a0\u00a0\u00a0 {\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 D3D12_FEATURE_DATA_D3D12_OPTIONS17 options17;\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (SUCCEEDED(device-&gt;CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS17, &amp;options17, sizeof(options17))))\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 { \u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return !!options17.ManualWriteTrackingResourceSupported;\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\u00a0\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return false;\u00a0\r\n\u00a0\u00a0\u00a0 }\u00a0<\/code><\/pre>\n<p><span data-contrast=\"auto\">The D3D12 runtime will always set ManualWriteTrackingResourceSupported to FALSE. However, PIX and (other graphics debugging tools) will intercept your API call and override ManualWriteTrackingResourceSupported to TRUE when appropriate.<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"auto\">If ManualWriteTrackingResourceSupported is TRUE, then you can set D3D12_HEAP_FLAG_TOOLS_USE_MANUAL_WRITE_TRACKING as a heap flag when you create a mappable heap or committed resource:<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">typedef enum D3D12_HEAP_FLAGS\u00a0\r\n\u00a0\u00a0\u00a0 {\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 D3D12_HEAP_FLAG_NONE = 0,\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 D3D12_HEAP_FLAG_SHARED = 0x1,\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 D3D12_HEAP_FLAG_DENY_BUFFERS = 0x4,\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 D3D12_HEAP_FLAG_ALLOW_DISPLAY = 0x8,\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 D3D12_HEAP_FLAG_SHARED_CROSS_ADAPTER = 0x20,\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES = 0x40,\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES = 0x80,\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 D3D12_HEAP_FLAG_HARDWARE_PROTECTED = 0x100,\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 D3D12_HEAP_FLAG_ALLOW_WRITE_WATCH = 0x200,\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 D3D12_HEAP_FLAG_ALLOW_SHADER_ATOMICS = 0x400,\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 D3D12_HEAP_FLAG_CREATE_NOT_RESIDENT = 0x800,\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 D3D12_HEAP_FLAG_CREATE_NOT_ZEROED = 0x1000,\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 D3D12_HEAP_FLAG_TOOLS_USE_MANUAL_WRITE_TRACKING = 0x2000,\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES = 0,\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS = 0xc0,\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES = 0x44,\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES = 0x84\u00a0\r\n\u00a0\u00a0\u00a0 } D3D12_HEAP_FLAGS;\u00a0<\/code><\/pre>\n<p><span data-contrast=\"auto\">This flag tells PIX (or other graphics debugging tools) to turn off WRITE_WATCH tracking on the heap or committed resource. The D3D12 runtime will reject any attempt to set this flag when ManualWriteTrackingResourceSupported is FALSE.<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"auto\">After resource\/heap creation, if you map your resource on the CPU then you must tell PIX any time you modify the mapped bytes on the CPU timeline by calling ID3D12ManualWriteTrackingResource::TrackWrite from d3d12sdklayers.h:<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">\u00a0\u00a0\u00a0 ID3D12ManualWriteTrackingResource : public IUnknown\u00a0\r\n\u00a0\u00a0\u00a0 {\u00a0\r\n\u00a0\u00a0\u00a0 public:\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 virtual void STDMETHODCALLTYPE TrackWrite(\u00a0\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 UINT Subresource,\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 _In_opt_\u00a0 const D3D12_RANGE *pWrittenRange) = 0;\u00a0\r\n\u00a0\u00a0\u00a0 };\u00a0<\/code><\/pre>\n<p><span data-contrast=\"auto\">You can get this interface by QueryInterface()\u2019ing for it off your ID3D12Resource*.<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"auto\">You must call ID3D12ManualWriteTrackingResource::TrackWrite after you modify your mapped bytes, but before you call ID3D12CommandQueue::ExecuteCommandLists() to execute any command list whose GPU work may depend on your modifications.<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary If you\u2019re using GPU_UPLOAD heaps and you are experiencing capture-time performance issues when you launch your application via PIX (e.g. your game\u2019s framerate drops) then read on to learn how ID3D12ManualWriteTrackingResource might help you. &nbsp; Background When taking a GPU Capture, PIX (and other graphics debugging tools) often use WRITE_WATCH to automatically detect modifications [&hellip;]<\/p>\n","protected":false},"author":1899,"featured_media":4769,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-6094","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-pix"],"acf":[],"blog_post_summary":"<p>Summary If you\u2019re using GPU_UPLOAD heaps and you are experiencing capture-time performance issues when you launch your application via PIX (e.g. your game\u2019s framerate drops) then read on to learn how ID3D12ManualWriteTrackingResource might help you. &nbsp; Background When taking a GPU Capture, PIX (and other graphics debugging tools) often use WRITE_WATCH to automatically detect modifications [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/pix\/wp-json\/wp\/v2\/posts\/6094","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/pix\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/pix\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/pix\/wp-json\/wp\/v2\/users\/1899"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/pix\/wp-json\/wp\/v2\/comments?post=6094"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/pix\/wp-json\/wp\/v2\/posts\/6094\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/pix\/wp-json\/wp\/v2\/media\/4769"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/pix\/wp-json\/wp\/v2\/media?parent=6094"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/pix\/wp-json\/wp\/v2\/categories?post=6094"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/pix\/wp-json\/wp\/v2\/tags?post=6094"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}