DirectX 12: Properlt syncrhonizing resources access from different command queue

I am writing a D3D12 application where I have two command queues. One for rendering and another for data copying.As I can’t post here all the code here is the exec flow with some of the actual code in the important areas:

The app consists of two stages: 1) Render to backbuffer which has two RTVs (double buffering). 2) Copy the last presented buffer to another D3D texture resource.
I must use separate queues. That’s mandatory.

cmdQueue1 – rendering queue created as D3D12_COMMAND_LIST_TYPE_DIRECT

cmdQueue2 – copy queue created as D3D12_COMMAND_LIST_TYPE_COPY.

  1. Submit cmdQueue1 for rendering.

  2. Present and sync:

    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    <code>ID3D12CommandList* ppCommandLists[] = { m_commandList.Get() };
    m_commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
    HRESULT res = m_swapChain->Present(1, 0);
    assert(SUCCEEDED(res));
    //make sure rendering has finished before flipping:
    const UINT64 currentFenceValue = m_fenceValues[m_frameIndex];
    res = (m_commandQueue->Signal(m_fence.Get(), currentFenceValue));
    assert(SUCCEEDED(res));
    m_frameIndex = m_swapChain->GetCurrentBackBufferIndex();
    if (m_fence->GetCompletedValue() < m_fenceValues[m_frameIndex])
    {
    res = m_fence->SetEventOnCompletion(m_fenceValues[m_frameIndex], m_fenceEvent);
    assert(SUCCEEDED(res));
    WaitForSingleObjectEx(m_fenceEvent, INFINITE, FALSE);
    }
    m_fenceValues[m_frameIndex] = currentFenceValue + 1;
    </code>
    <code>ID3D12CommandList* ppCommandLists[] = { m_commandList.Get() }; m_commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists); HRESULT res = m_swapChain->Present(1, 0); assert(SUCCEEDED(res)); //make sure rendering has finished before flipping: const UINT64 currentFenceValue = m_fenceValues[m_frameIndex]; res = (m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); assert(SUCCEEDED(res)); m_frameIndex = m_swapChain->GetCurrentBackBufferIndex(); if (m_fence->GetCompletedValue() < m_fenceValues[m_frameIndex]) { res = m_fence->SetEventOnCompletion(m_fenceValues[m_frameIndex], m_fenceEvent); assert(SUCCEEDED(res)); WaitForSingleObjectEx(m_fenceEvent, INFINITE, FALSE); } m_fenceValues[m_frameIndex] = currentFenceValue + 1; </code>
    ID3D12CommandList* ppCommandLists[] = { m_commandList.Get() };
    m_commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
    HRESULT res = m_swapChain->Present(1, 0);
    assert(SUCCEEDED(res));
    //make sure rendering has finished before flipping:
    const UINT64 currentFenceValue = m_fenceValues[m_frameIndex];
    res = (m_commandQueue->Signal(m_fence.Get(), currentFenceValue));
    assert(SUCCEEDED(res));
    m_frameIndex = m_swapChain->GetCurrentBackBufferIndex();
    if (m_fence->GetCompletedValue() < m_fenceValues[m_frameIndex])
    {
      res = m_fence->SetEventOnCompletion(m_fenceValues[m_frameIndex], m_fenceEvent);
      assert(SUCCEEDED(res));
      WaitForSingleObjectEx(m_fenceEvent, INFINITE, FALSE);
    }
    m_fenceValues[m_frameIndex] = currentFenceValue + 1;
    
  3. Now comes the copy part which uses cmdQueue2:

    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    <code>ID3D12CommandList* ppCommandLists[] = { m_dataCopyCommandList };
    m_commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
    m_commandQueue->Signal(m_pCopyFence, m_nCopyFenceVal);
    if (pFence->GetCompletedValue() < nFenceValue)
    {
    pFence->SetEventOnCompletion(nFenceValue, m_event);
    WaitForSingleObject(m_event, INFINITE);
    }
    m_nCopyFenceVal++;
    </code>
    <code>ID3D12CommandList* ppCommandLists[] = { m_dataCopyCommandList }; m_commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists); m_commandQueue->Signal(m_pCopyFence, m_nCopyFenceVal); if (pFence->GetCompletedValue() < nFenceValue) { pFence->SetEventOnCompletion(nFenceValue, m_event); WaitForSingleObject(m_event, INFINITE); } m_nCopyFenceVal++; </code>
    ID3D12CommandList* ppCommandLists[] = { m_dataCopyCommandList };
    m_commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
    m_commandQueue->Signal(m_pCopyFence, m_nCopyFenceVal);
    if (pFence->GetCompletedValue() < nFenceValue)
    {
       pFence->SetEventOnCompletion(nFenceValue, m_event);
       WaitForSingleObject(m_event, INFINITE);
    }
    m_nCopyFenceVal++;
    

Each queue is synchronized with its own event object and fence.

The application works fine. Also the copy of the backbuffer to an auxiliary texture resource seems to be ok.But the output window spits from time to time the following error:

D3D12 ERROR: ID3D12CommandQueue::ExecuteCommandLists:
Non-simultaneous-access Texture Resource (0x00000212AC79B090:’Unnamed
Object’) is still referenced by write|transition_barrier|assert_read
GPU operations in-flight on another Command Queue
(0x00000212A6381C90:’Unnamed ID3D12CommandQueue Object’). It is not
safe to start read|transition_barrier GPU operations now on this
Command Queue (0x00000212A609AC20:’Unnamed ID3D12CommandQueue
Object’). This can result in race conditions and application
instability. [ EXECUTION ERROR #1047:
OBJECT_ACCESSED_WHILE_STILL_IN_USE]

I am not sure I understand why there can be an issue as I make sure the first queue is done executing before moving to the next one. Also, all this logic currently runs on the same thread. Is it safe to ignore the above warning or I am missing something in my code?

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật