-
Notifications
You must be signed in to change notification settings - Fork 127
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Testing: Dump DX12 resources for drawcall #1356
Conversation
CI gfxreconstruct build queued with queue ID 84259. |
6100b35
to
bbf556e
Compare
CI gfxreconstruct build queued with queue ID 84294. |
bbf556e
to
e532782
Compare
CI gfxreconstruct build queued with queue ID 84295. |
e532782
to
6482ca8
Compare
CI gfxreconstruct build queued with queue ID 84306. |
6482ca8
to
4c76ce1
Compare
CI gfxreconstruct build queued with queue ID 84312. |
4c76ce1
to
21e2836
Compare
CI gfxreconstruct build queued with queue ID 84372. |
21e2836
to
1280f13
Compare
CI gfxreconstruct build queued with queue ID 84374. |
1280f13
to
616acaa
Compare
CI gfxreconstruct build queued with queue ID 84376. |
616acaa
to
8ef173a
Compare
CI gfxreconstruct build queued with queue ID 84487. |
8ef173a
to
eafb50a
Compare
CI gfxreconstruct build queued with queue ID 84640. |
|
||
// TODO: This class copys a lot of code to write json from VulkanExportJsonConsumerBase. | ||
// We might need a class for writing json. | ||
class Dx12DumpResources |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dx12DumpResources
output json and resources. A lot of json code are copied from VulkanExportJsonConsumerBase
. We should have a common class for them.
} | ||
}; | ||
|
||
class Dx12BrowseConsumer : public Dx12Consumer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dx12BrowseConsumer
browses the file before replay to find the target drawcall code index and some key code indices, and track resource infos. That could help replay easier. But it doesn't track render target infos because the useful info is replay cpuDescriptor. It's only available in replay.
template <format::ApiCallId Id> | ||
struct CustomReplayPreCall | ||
{ | ||
template <typename... Args> | ||
static void Dispatch(Dx12ReplayConsumerBase*, Args...) | ||
{} | ||
}; | ||
|
||
template <format::ApiCallId Id> | ||
struct CustomReplayPostCall | ||
{ | ||
template <typename... Args> | ||
static void Dispatch(Dx12ReplayConsumerBase*, Args...) | ||
{} | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add CustomReplayPreCall
and CustomReplayPostCall
in every function call to track resources and add copy resource cmd.
framework/decode/dx12_object_info.h
Outdated
@@ -303,7 +310,8 @@ struct D3D12ResourceInfo : DxObjectExtraInfo | |||
std::map<uint64_t, uint64_t> mapped_gpu_addresses; | |||
std::map<uint64_t, graphics::Dx12ShaderIdentifier> mapped_shader_ids; | |||
|
|||
D3D12_RESOURCE_DESC1 desc = {}; | |||
D3D12_RESOURCE_DESC1 desc = {}; | |||
D3D12_RESOURCE_STATES current_state{ D3D12_RESOURCE_STATE_COMMON }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It needs to track the current state of resources for change state for copy resources.
(modified_initial_resource_state & D3D12_RESOURCE_STATE_ALL_SHADER_RESOURCE)) | ||
{ | ||
// shader resources can't change state after SetGraphicsRootDescriptorTable. | ||
// But even if it changes state and copy resources before SetGraphicsRootDescriptorTable, | ||
// it can't solve it, because it also has to copy resources after drawcall. | ||
// In this case, adding a COPY_SOURCE state here, so it doesn't need to change state for copy resources. | ||
modified_initial_resource_state |= D3D12_RESOURCE_STATE_COPY_SOURCE; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shader resources can't change state after SetGraphicsRootDescriptorTable. In this case, adding a COPY_SOURCE state for shader resource, so it doesn't need to change state for copy resources.
if (barriers[i].Transition->decoded_value->StateAfter & D3D12_RESOURCE_STATE_ALL_SHADER_RESOURCE) | ||
{ | ||
// shader resources can't change state after SetGraphicsRootDescriptorTable. | ||
// Adding a COPY_SOURCE state here, so it doesn't need to change state for copy resources. | ||
barriers[i].Transition->decoded_value->StateAfter |= D3D12_RESOURCE_STATE_COPY_SOURCE; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shader resources can't change state after SetGraphicsRootDescriptorTable. In this case, adding a COPY_SOURCE state for shader resource, so it doesn't need to change state for copy resources.
hr = graphics::dx12::WaitForQueue(queue, fence, UINT64_MAX); | ||
GFXRECON_ASSERT(SUCCEEDED(hr)); | ||
|
||
dump_resources_->WriteResources(track_dump_resources_); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After ExecuteCommandLists and WaitForQueue, output the resources.
if (track_dump_resources_.target.begin_renderpass_code_index == 0) | ||
{ | ||
// The program doesn't use renderpass. | ||
AddCopyResourceCommandsForAfterDrawcall(commandlist); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here add copy resources or renderpass command for after drawcall
After adding copy resource in after drawcall, it still has to run the original ExecuteCommandLists, not a new ExecuteCommandLists because some FIllMemoryCommand runs before the original ExecuteCommandLists. If it runs a new ExecuteCommandLists, it might miss FIllMemoryCommand.
for (uint32_t i = 0; i < NumRenderTargets; ++i) | ||
{ | ||
rt_descs[i].EndingAccess->decoded_value->Type = D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE; | ||
} | ||
|
||
auto ds_desc = pDepthStencil->GetMetaStructPointer(); | ||
if (ds_desc) | ||
{ | ||
ds_desc->DepthEndingAccess->decoded_value->Type = D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE; | ||
ds_desc->StencilEndingAccess->decoded_value->Type = D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In BeginRednerPass, the EndingAcccess have to be PRESERVE to keep the the render process for this following inserted renderpass, or it will clear the render target.
eafb50a
to
c802431
Compare
CI gfxreconstruct build queued with queue ID 84671. |
c802431
to
c61b4b3
Compare
CI gfxreconstruct build queued with queue ID 84673. |
for (uint32_t i = 0; i < rt_descs_size; ++i) | ||
{ | ||
rt_descs[i].cpuDescriptor = track_dump_resources_.replay_render_target_handles[i]; | ||
rt_descs[i].BeginningAccess.Type = D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE; | ||
rt_descs[i].EndingAccess.Type = D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE; | ||
} | ||
|
||
D3D12_RENDER_PASS_DEPTH_STENCIL_DESC* p_ds_desc = nullptr; | ||
D3D12_RENDER_PASS_DEPTH_STENCIL_DESC ds_desc{}; | ||
if (track_dump_resources_.depth_stencil_heap_id != 0) | ||
{ | ||
p_ds_desc = &ds_desc; | ||
ds_desc.cpuDescriptor = track_dump_resources_.replay_depth_stencil_handle; | ||
ds_desc.DepthBeginningAccess.Type = D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE; | ||
ds_desc.StencilBeginningAccess.Type = D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE; | ||
ds_desc.DepthEndingAccess.Type = D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE; | ||
ds_desc.StencilEndingAccess.Type = D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is to insert renderpass in before drawcall. The BeginningAccess an EndingAcccess of the renderpass have to be PRESERVE to keep the the render process from the previous renderpass and for this following inserted renderpass, or it will clear the render target.
CI gfxreconstruct build # 3665 running. |
CI gfxreconstruct build # 3665 failed. |
CI gfxreconstruct build queued with queue ID 117619. |
CI gfxreconstruct build # 3673 running. |
It shouldn't change state in ResourceBarrier. It should track the AfterState in ResourceBarrier, and then change it in ExecuteCommandList. But the state could be wrong for CopyResource, if ResourceBarrier is in another commandlist, and the commandlist is executed after the target drawcall, we couldn't know the correct state.
1. To output readable data. Set "TEST_READABLE = true" in dx12_dump_resources.cpp. This feature is only for test because data type could be various. But here uses fixed type. float for vertex, index, constant buffer. image for shader resource, render target. 2. To skip dump shader resources, Set "TEST_SHADER_RES = false" in dx12_replay_consumer_base.cpp. Now, dump shader resources could cost too much memory to cause crash.
CI gfxreconstruct build queued with queue ID 117698. |
CI gfxreconstruct build # 3674 running. |
CI gfxreconstruct build queued with queue ID 117731. |
CI gfxreconstruct build # 3675 running. |
CI gfxreconstruct build # 3675 passed. |
CI gfxreconstruct build queued with queue ID 118212. |
CI gfxreconstruct build # 3676 running. |
CI gfxreconstruct build # 3676 passed. |
Keep track of pending resource state changes in command list info, then apply the pending state changes in execute command lists.
Use a map to track descriptors so that when a new descriptor is created in the same location as an existing descriptor, the existing descriptor is removed.
CI gfxreconstruct build queued with queue ID 119197. |
CI gfxreconstruct build # 3682 running. |
CI gfxreconstruct build # 3682 passed. |
CI gfxreconstruct-extended build queued with queue ID 130708. |
CI gfxreconstruct-extended build # 315 running. |
CI gfxreconstruct-extended build # 315 passed. |
Test sample: D3D12HelloTexture. It's for renderpass test. I added renderpass, constant buffer, more triangles, and test code about copy resource and separated renderpass.
https://github.com/locke-lunarg/DirectX-Graphics-Samples/tree/test-dump
For not renderpass case, now, I tested HelloWorld project in DirectX-Graphics-Samples. I'm doing more tests.
Add option:
--dump-resources drawcall-n
. n is the index of drawcall.To output readable data. Set
TEST_READABLE = true
indx12_dump_resources.cpp
.Float for vertex, index, constant buffer.
Image for shader resource, render target.
The basic concept:
Not renderpass
: Add copy resource command in before and after drawcall.E.g.:
Original
New
Renderpass
: Add renderpasses in before and after drawcall.E.g.:
Original
New
According to my test, it is ok to insert the renderpass in anyplace in the original renderpass. And then, the EndingAcccess of the renderpass and the BeginningAccess of following renderpasses have to be PRESERVE to keep the the rendering process for this following renderpass, or it will clear the render target.