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

Fix potential crash when resizing windows when using D3D12 graphics backend #829

Closed

Conversation

FelixK15
Copy link
Contributor

Fixed the crash described in #822

The issues basically boils down to this:
When the user resized the window at exactly the wrong time, the current commandbuffer that the GPU's processing is the commandbuffer that writes to the backbuffer at index 0.

When, at that time, the resize happens, the code sets windows[current_window].currentBuffer = 0 inside kinc_g4_begin(). this results in the commandqueue trying to write to the wrong backbuffer for the next frame (basically it would then try to write to backbuffer 0 again even though it expects to write to backbuffer 1 - if that makes sense).

This requires further testing with an actual workload as I only tested this with the input test.

My testcode for this basically looked like this:

static void update(void *data) {
	static int timer = 0;
	++timer;

	if ( timer == 3 ) {
		ShowWindow(hwnd, SW_MINIMIZE); //This was implemented inside Backends\System\Windows\Sources\kinc\backend\window.c.h
	}

	if (timer == 6) {
		ShowWindow(hwnd, SW_SHOWNORMAL);  //This was implemented inside Backends\System\Windows\Sources\kinc\backend\window.c.h
		timer = 0;
	}

	kinc_g4_begin(0);
	kinc_g4_clear(KINC_G4_CLEAR_COLOR, 0, 0.0f, 0);
	kinc_g4_end(0);
	kinc_g4_swap_buffers();
}

int kickstart(int argc, char **argv) {
        kinc_init("Shader", 1024, 768, NULL, NULL);
	kinc_set_update_callback(update, NULL);
	kinc_start();

        return 0;
}

Before my change the crash would happen at some point preceeded by logspam that read like this:

D3D12 ERROR: ID3D12CommandQueue::ExecuteCommandLists: A command list, which writes to a swapchain back buffer, may only be executed when that back buffer is the back buffer that will be presented during the next call to Present*. Such a back buffer is also referred to as the "current back buffer". Swap Chain: 0x000002793F1D5D40:'Unnamed Object' - Current Back Buffer Buffer: 0x000002793F22F1B0:'Backbuffer (index 0)' - Attempted Write Buffer: 0x000002793F230070:'Backbuffer (index 1)' [ STATE_SETTING ERROR #907: EXECUTECOMMANDLISTS_WRONGSWAPCHAINBUFFERREFERENCE]

@RobDangerous
Copy link
Member

Thanks a ton for the pull request. It was not the actual fix but it got me on the right track.
I put this code at the start of update to test:

if (resized) {
	kinc_window_resize(0, 400, 400);
}
else {
	kinc_window_resize(0, 600, 600);
}
resized = !resized;

Originally this caused
D3D12 ERROR: ID3D12Resource2::<final-release>: CORRUPTION: An ID3D12Resource object (0x000001AB94F33830:'Backbuffer (index 0)') is referenced by GPU operations in-flight on Command Queue (0x000001AB8E8270F0:'Unnamed ID3D12CommandQueue Object'). It is not safe to final-release objects that may have GPU operations pending. This can result in application instability. [ EXECUTION ERROR #921: OBJECT_DELETED_WHILE_STILL_IN_USE] and kinc_microsoft_affirm triggers in line 531 in Direct3D12.c.h (kinc_g5_begin).

With your fix for me it caused
D3D12 ERROR: ID3D12CommandQueue::ExecuteCommandLists: A command list, which writes to a swapchain back buffer, may only be executed when that back buffer is the back buffer that will be presented during the next call to Present*. Such a back buffer is also referred to as the "current back buffer". Swap Chain: 0x000002E2E5BE5FC0:'Unnamed Object' - Current Back Buffer Buffer: 0x000002E2E5D3F5A0:'Backbuffer (index 0)' - Attempted Write Buffer: 0x000002E2DF5D7B40:'Backbuffer (index 1)' [ STATE_SETTING ERROR #907: EXECUTECOMMANDLISTS_WRONGSWAPCHAINBUFFERREFERENCE] D3D12: Removing Device. D3D12 ERROR: ID3D12Device::RemoveDevice: Device removal has been triggered for the following reason (DXGI_ERROR_ACCESS_DENIED: The application attempted to use a resource it does not access to. This could be, for example, rendering to a texture while only having read access.). [ EXECUTION ERROR #232: DEVICE_REMOVAL_PROCESS_AT_FAULT] and kinc_microsoft_affirm triggers in line 592 in Direct3D12.c.h (kinc_g5_swap_buffers).

I do not fully understand yet if that's my fault somewhere or if D3D itself wants things to go back to the first framebuffer after a resize.
Anyway, kinc_g4_begin has a kinc_g5_command_list_execute early on and we delete all framebuffers immediately afterwards on resize, so that's not good. On resize I now wait for it to finish and that seems to fix it.

@mikaib
Copy link

mikaib commented Jul 21, 2024

Lovely.

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.

3 participants