Skip to content
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

Closed
wants to merge 15 commits into from

Conversation

locke-lunarg
Copy link
Contributor

@locke-lunarg locke-lunarg commented Nov 15, 2023

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 in dx12_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

cmd->Reset();
...
cmd->Draw();
...
cmd->Draw();  -> Target
...
cmd->End();

New

cmd->Reset();
...
cmd->Draw();
...
cmd->CopyResource(); -> Add
cmd->draw();  -> Target
cmd->CopyResource(); -> Add
...
cmd->End();

Renderpass: Add renderpasses in before and after drawcall.
E.g.:
Original

cmd->Reset();
...
cmd->BeginRenderPass();
...
cmd->Draw();
...
cmd->Draw();  -> Target
...
cmd->EndRenderPass();
...
cmd->End();

New

cmd->Reset();
...
cmd->BeginRenderPass();
...
cmd->Draw();
...
cmd->EndRenderPass();    -> Add
cmd->CopyResource();     -> Add
cmd->BeginRenderPass();  -> Add
cmd->Draw();  -> Target
cmd->EndRenderPass();    -> Add
cmd->CopyResource();     -> Add
cmd->BeginRenderPass();  -> Add
...
cmd->EndRenderPass();
...
cmd->End();

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.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 84259.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 84294.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 84295.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 84306.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 84312.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 84372.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 84374.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 84376.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 84487.

@ci-tester-lunarg
Copy link

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
Copy link
Contributor Author

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
Copy link
Contributor Author

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.

Comment on lines +31 to +45
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...)
{}
};
Copy link
Contributor Author

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.

@@ -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 };
Copy link
Contributor Author

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.

Comment on lines 1219 to 1225
(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;
Copy link
Contributor Author

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.

Comment on lines 3821 to 3833
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;
Copy link
Contributor Author

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_);
Copy link
Contributor Author

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);
Copy link
Contributor Author

@locke-lunarg locke-lunarg Nov 16, 2023

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.

Comment on lines +3927 to +4002
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;
Copy link
Contributor Author

@locke-lunarg locke-lunarg Nov 16, 2023

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.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 84671.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 84673.

Comment on lines +4003 to +4213
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;
Copy link
Contributor Author

@locke-lunarg locke-lunarg Nov 16, 2023

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.

@locke-lunarg locke-lunarg marked this pull request as ready for review November 16, 2023 07:13
@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 3665 running.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 3665 failed.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 117619.

@ci-tester-lunarg
Copy link

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-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 117698.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 3674 running.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 117731.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 3675 running.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 3675 passed.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 118212.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 3676 running.

@ci-tester-lunarg
Copy link

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-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 119197.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 3682 running.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 3682 passed.

@ci-tester-lunarg
Copy link

CI gfxreconstruct-extended build queued with queue ID 130708.

@ci-tester-lunarg
Copy link

CI gfxreconstruct-extended build # 315 running.

@ci-tester-lunarg
Copy link

CI gfxreconstruct-extended build # 315 passed.

@locke-lunarg locke-lunarg marked this pull request as draft February 16, 2024 20:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants