0

I'm coding a C++ game from scratch using the Direct-X 12 API.

I'm using a few tutorials: Braynzar Soft Direct-X 12 tutorial, Alian Direct-X 12 and a few others.

Each one I use runs and has no errors. But I have a slight problem.

In professional games and game engines, they can use a dedicated GPU to run their programs and sometimes at a low performance. BUT, when I use this tutorials or I code it myself, it uses both of my GPUs simultaneously. Why is that? Is there some bug within the code? Does Direct-X 12 just multi-GPU automatically? Can I prevent this and how? There wouldn't be a problem with this, but I would like, if possible, to only use on GPU.

Simple code:

int32_t CALLBACK wWinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ LPWSTR, _In_ int32_t)
{
    HRESULT ReturnCode = S_OK;
#ifdef _SCPDebug
    ID3D12Debug3* D3D12DebugInterface = nullptr;
    IDXGIInfoQueue* DXGIDebugInfoQueue = nullptr;
    
    ReturnCode = D3D12GetDebugInterface(IID_PPV_ARGS(&D3D12DebugInterface));
    if (ReturnCode != S_OK)
    {
        return ReturnCode;
    }

    D3D12DebugInterface->EnableDebugLayer();
    D3D12DebugInterface->SetEnableGPUBasedValidation(TRUE);

    ReturnCode = DXGIGetDebugInterface1(0, IID_PPV_ARGS(&DXGIDebugInfoQueue));
    if (ReturnCode != S_OK)
    {
        return ReturnCode;
    }

    ReturnCode = DXGIDebugInfoQueue->SetBreakOnSeverity(DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, TRUE);
    if (ReturnCode != S_OK)
    {
        return ReturnCode;
    }

    ReturnCode = DXGIDebugInfoQueue->SetBreakOnSeverity(DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, TRUE);
    if (ReturnCode != S_OK)
    {
        return ReturnCode;
    }
#endif

    IDXGIFactory7* DXGIFactory = nullptr;
#ifdef _SCPDebug
    ReturnCode = CreateDXGIFactory2(1, IID_PPV_ARGS(&DXGIFactory));
#else
    ReturnCode = CreateDXGIFactory2(0, IID_PPV_ARGS(&DXGIFactory));
#endif
    if (ReturnCode != S_OK)
    {
        return ReturnCode;
    }

    BOOL SupportsVariableRefreshRate = FALSE;
    ReturnCode = DXGIFactory->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &SupportsVariableRefreshRate, sizeof(BOOL));
    if (ReturnCode != S_OK)
    {
        return ReturnCode;
    }

    IDXGIAdapter4* DXGIAdapter = nullptr;
    ReturnCode = DXGIFactory->EnumAdapterByGpuPreference(0, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, IID_PPV_ARGS(&DXGIAdapter));
    if (ReturnCode != S_OK)
    {
        return ReturnCode;
    }

    ID3D12Device8* D3D12Device = nullptr;
#ifdef _SCPDebug
    ID3D12InfoQueue* D3D12DeviceDebugInfoQueue = nullptr;
#endif
    ReturnCode = D3D12CreateDevice(DXGIAdapter, D3D_FEATURE_LEVEL_12_1, IID_PPV_ARGS(&D3D12Device));
    if (ReturnCode != S_OK)
    {
        return ReturnCode;
    }

    ReturnCode = D3D12Device->SetName(L"SCP-Site Breach::Engine::Direct-X 12::Device8");
    if (ReturnCode != S_OK)
    {
        return ReturnCode;
    }

#ifdef _SCPDebug
    ReturnCode = D3D12Device->QueryInterface(&D3D12DeviceDebugInfoQueue);
    if (ReturnCode != S_OK)
    {
        return ReturnCode;
    }

    ReturnCode = D3D12DeviceDebugInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, TRUE);
    if (ReturnCode != S_OK)
    {
        return ReturnCode;
    }

    ReturnCode = D3D12DeviceDebugInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, TRUE);
    if (ReturnCode != S_OK)
    {
        return ReturnCode;
    }
#endif

    ID3D12DescriptorHeap* D3D12DSDescriptorHeap = nullptr;
    ID3D12Resource2* D3D12DS = nullptr;
    
    D3D12_DESCRIPTOR_HEAP_DESC DescriptorHeapDesc = {};
    DescriptorHeapDesc.NumDescriptors = 1;
    DescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
    DescriptorHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
    ReturnCode = D3D12Device->CreateDescriptorHeap(&DescriptorHeapDesc, IID_PPV_ARGS(&D3D12DSDescriptorHeap));
    if (FAILED(ReturnCode))
    {
        return ReturnCode;
    }

    ReturnCode = D3D12DSDescriptorHeap->SetName(L"SCP-Site Breach::Engine::Direct-X 12::Depth Stencil Descriptor Heap");
    if (FAILED(ReturnCode))
    {
        return ReturnCode;
    }

    D3D12_CLEAR_VALUE OptimizedDepthClearValue;
    OptimizedDepthClearValue.DepthStencil.Depth = 1.0f;
    OptimizedDepthClearValue.DepthStencil.Stencil = 0;
    OptimizedDepthClearValue.Format = DXGI_FORMAT_D32_FLOAT;

    D3D12_HEAP_PROPERTIES HeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);
    D3D12_RESOURCE_DESC HeapDesc = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_D32_FLOAT, 1920, 1080, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL);

    ReturnCode = D3D12Device->CreateCommittedResource(&HeapProperties, D3D12_HEAP_FLAG_NONE, &HeapDesc, D3D12_RESOURCE_STATE_DEPTH_WRITE, &OptimizedDepthClearValue, IID_PPV_ARGS(D3D12DS));
    if (FAILED(ReturnCode))
    {
        return ReturnCode;
    }

    ReturnCode = D3D12DS->SetName(L"SCP-Site Breach::Engine::Direct-X 12::Depth Stencil Heap");
    if (FAILED(ReturnCode))
    {
        return ReturnCode;
    }

    D3D12_DEPTH_STENCIL_VIEW_DESC DepthStencilViewDesc = {};
    DepthStencilViewDesc.Format = DXGI_FORMAT_D32_FLOAT;
    DepthStencilViewDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
    DepthStencilViewDesc.Flags = D3D12_DSV_FLAG_NONE;

    D3D12Device->CreateDepthStencilView(D3D12DS, &DepthStencilViewDesc, D3D12DSDescriptorHeap->GetCPUDescriptorHandleForHeapStart());

    ID3D12Fence1* D3D12Fence = nullptr;
    uint64_t FenceValue = 0ULL;
    HANDLE FenceEvent = nullptr;

    ReturnCode = D3D12Device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&D3D12Fence));
    if (ReturnCode != S_OK)
    {
        return ReturnCode;
    }

    ReturnCode = D3D12Fence->SetName(L"SCP-Site Breach::Engine::Direct-X 12::Sync::Fence");
    if (ReturnCode != S_OK)
    {
        return ReturnCode;
    }

    HANDLE FenceEvent = CreateEventW(nullptr, FALSE, FALSE, L"SCP-Site Breach::Engine::Direct-X 12::Sync::Fence Event");
    if (FenceEvent == nullptr)
    {
        return E_UNEXPECTED;
    }

    ID3D12RootSignature* D3D12RootSignature = nullptr;
    {
        D3D12_ROOT_SIGNATURE_DESC1 Desc = {};
        Desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | D3D12_ROOT_SIGNATURE_FLAG_DENY_VERTEX_SHADER_ROOT_ACCESS |
            D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS | D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS |
            D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS | D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS;
        Desc.NumParameters = 0;
        Desc.NumStaticSamplers = 0;
        Desc.pParameters = nullptr;
        Desc.pStaticSamplers = nullptr;

        D3D12_VERSIONED_ROOT_SIGNATURE_DESC RootSignatureDescVersion = {};
        RootSignatureDescVersion.Desc_1_1 = Desc;
        RootSignatureDescVersion.Version = D3D_ROOT_SIGNATURE_VERSION_1_1;

        ID3D10Blob* D3D12SignatureBlob = nullptr;
        ID3D10Blob* D3D12ErrorBlob = nullptr;

        ReturnCode = D3D12SerializeVersionedRootSignature(&RootSignatureDescVersion, &D3D12SignatureBlob &D3D12ErrorBlob);
        if (ReturnCode != S_OK)
        {
            return ReturnCode;
        }

        ReturnCode = D3D12Device->CreateRootSignature(0, D3D12SignatureBlob->GetBufferPointer(), D3D12SignatureBlob->GetBufferSize(), IID_PPV_ARGS(&D3D12RootSignature));
        if (ReturnCode != S_OK)
        {
            return ReturnCode;
        }

        ReturnCode =D3D12RootSignature->SetName(L"SCP-Site Breach::Engine::Direct-X 12::Root Signature");
        if (ReturnCode != S_OK)
        {
            return ReturnCode;
        }

        D3D12SignatureBlob->Release();
        D3D12SignatureBlob = nullptr;
    }

    D3D12_SHADER_BYTECODE D3D12PixelShader = {};
    D3D12_SHADER_BYTECODE D3D12VertexShader = {};
    
    std::ifstream PixelShader("PixelShader.cso", std::ios_base::binary | std::ios_base::in);
    auto FileSize = PixelShader.tellg();
    PixelShader.seekg(0, std::iostream::end);
    FileSize += PixelShader.tellg() - FileSize;
    PixelShader.seekg(0, std::iostream::beg);

    std::ifstream VertexShader("VertexShader.cso", std::ios_base::binary | std::ios_base::in);
    auto FileSize2 = VertexShader.tellg();
    VertexShader.seekg(0, std::iostream::end);
    FileSize2 += VertexShader.tellg() - FileSize2;
    VertexShader.seekg(0, std::iostream::beg);

    D3D12PixelShader.BytecodeLength = msl::utilities::SafeInt<SIZE_T>(FileSize.operator long long());
    D3D12PixelShader.pShaderBytecode = malloc(D3D12PixelShader.BytecodeLength);
    PixelShader.read(reinterpret_cast<char*>(const_cast<void*>(D3D12PixelShader.pShaderBytecode)), msl::utilities::SafeInt<long long>(D3D12PixelShader.BytecodeLength));

    D3D12VertexShader.BytecodeLength = msl::utilities::SafeInt<SIZE_T>(FileSize2.operator long long());
    D3D12VertexShader.pShaderBytecode = malloc(D3D12VertexShader.BytecodeLength);
    VertexShader.read(reinterpret_cast<char*>(const_cast<void*>(D3D12VertexShader.pShaderBytecode)), msl::utilities::SafeInt<long long>(D3D12VertexShader.BytecodeLength));

    ID3D12PipelineState* D3D12PipelineStateObject = nullptr;
    
    static const D3D12_INPUT_ELEMENT_DESC s_inputElementDesc[2] =
    {
        { "SV_Position", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0,  D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,  0 },
        { "COLOR",       0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 16, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA , 0 }
    };

    D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
    psoDesc.InputLayout = { &s_inputElementDesc[0], _countof(s_inputElementDesc)};
    psoDesc.pRootSignature = D3D12RootSignature;
    psoDesc.PS = D3D12PixelShader;
    psoDesc.VS = D3D12VertexShader;
    psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
    psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
    psoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
    psoDesc.DSVFormat = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
    psoDesc.SampleMask = UINT_MAX;
    psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
    psoDesc.NumRenderTargets = 1;
    psoDesc.RTVFormats[0] = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
    psoDesc.SampleDesc.Count = 1;
    
    ReturnCode = D3D12Device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&D3D12PipelineStateObject));
    if (ReturnCode != S_OK)
    {
        return ReturnCode;
    }

    ReturnCode = D3D12PipelineStateObject->SetName(L"SCP-Site Breach::Engine::Direct-X 12::Pipeline State");
    if (ReturnCode != S_OK)
    {
        return ReturnCode;
    }

    ID3D12CommandQueue* D3D12CommandQueue = nullptr;
    
    D3D12_COMMAND_QUEUE_DESC Desc = {};
    Desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
    Desc.NodeMask = 0;
    Desc.Priority = 0;
    Desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;

    ReturnCode = D3D12Device->CreateCommandQueue(&Desc, IID_PPV_ARGS(&D3D12CommandQueue));
    if (ReturnCode != S_OK)
    {
        return ReturnCode;
    }

    ReturnCode = D3D12CommandQueue->SetName(L"SCP-Site Breach::Engine::Direct-X 12::Commands::Queue");
    if (ReturnCode != S_OK)
    {
        return ReturnCode;
    }

    ID3D12GraphicsCommandList6* D3D12CommandList = nullptr;
    ID3D12CommandAllocator* D3D12CommandAllocator = nullptr;

    ReturnCode = D3D12Device->CreateCommandAllocator(_Type, IID_PPV_ARGS(&D3D12CommandAllocator));
    if (ReturnCode != S_OK)
    {
        return ReturnCode;
    }

    ReturnCode = D3D12CommandAllocator->SetName(L"SCP-Site Breach::Engine::Direct-X 12::Commands::Allocator");
    if (ReturnCode != S_OK)
    {
        return ReturnCode;
    }

    ReturnCode = D3D12Device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, D3D12CommandAllocator, D3D12PipelineStateObject, IID_PPV_ARGS(&D3D12CommandList));
    if (ReturnCode != S_OK)
    {
        return ReturnCode;
    }

    ReturnCode = D3D12CommandList->SetName(L"SCP-Site Breach::Engine::Direct-X 12::Commands::List");
    if (ReturnCode != S_OK)
    {
        return ReturnCode;
    }

    ReturnCode = D3D12CommandList->Close();
    if (ReturnCode != S_OK)
    {
        return ReturnCode;
    }

    IDXGISwapChain4* DXGISwapChain = nullptr;
    ID3D12DescriptorHeap* D3D12SwapChainDescriptorHeap = nullptr;
    std::vector<ID3D12Resource2*> D3D12SwapChainBuffers = { nullptr, nullptr };

    WNDCLASSEXW WndClass = {};
    WndClass.cbSize = sizeof(WNDCLASSEXW);
    WndClass.hIcon = nullptr;
    WndClass.hIconSm = nullptr;
    WndClass.hCursor = LoadCursorW(nullptr, IDC_ARROW);
    WndClass.hInstance = GetModuleHandleW(nullptr);
    WndClass.lpfnWndProc = WindowProc;
    WndClass.lpszClassName = g_WndClassName.c_str();
    WndClass.hbrBackground = CreateSolidBrush(RGB(0, 0, 0));

    if (!RegisterClassExW(&WndClass))
    {
        return -1;
    }

    HWND m_GameWindow = CreateWindowExW(0, g_WndClassName.c_str(), L"Robo_Lab", WS_OVERLAPPED, 0, 0, 500, 500, nullptr, nullptr, GetModuleHandleW(nullptr), nullptr);

    SetWindowPos(m_GameWindow, HWND_TOP, 0, 0, 1920, 1080, SWP_SHOWWINDOW);

    DXGI_SWAP_CHAIN_DESC SwapChainDesc = {};
    SwapChainDesc.BufferCount = 2;
    SwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    SwapChainDesc.BufferDesc.Height = 1080;
    SwapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
    SwapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
    SwapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_STRETCHED;
    SwapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE;
    SwapChainDesc.BufferDesc.Width = 1920;
    SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    SwapChainDesc.OutputWindow = m_GameWindow;
    SwapChainDesc.SampleDesc.Count = 1;
    SwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
    SwapChainDesc.Windowed = true;

    ReturnCode = DXGIFactory->CreateSwapChain(D3D12CommandQueue, &SwapChainDesc, reinterpret_cast<IDXGISwapChain**>(&DXGISwapChain));
    if (ReturnCode != S_OK)
    {
        return ReturnCode;
    }

    D3D12_DESCRIPTOR_HEAP_DESC DescriptorHeapDesc = {};
    DescriptorHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
    DescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
    DescriptorHeapDesc.NumDescriptors = 2;

    ReturnCode = D3D12Device->CreateDescriptorHeap(&DescriptorHeapDesc, IID_PPV_ARGS(&D3D12SwapChainDescriptorHeap));
    if (ReturnCode != S_OK)
    {
        return ReturnCode;
    }

    uint32_t RTVDescriptorSize = D3D12Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);

    CD3DX12_CPU_DESCRIPTOR_HANDLE RTVDescriptorHandle(&D3D12SwapChainDescriptorHeap->GetCPUDescriptorHandleForHeapStart());

    for (size_t i = 0; i < 2; ++i)
    {
        DXGISwapChain->GetBuffer(i, IID_PPV_ARGS(&D3D12SwapChainBuffers.at(i)));
        wchar_t BufferName[64] = { 0 };
        swprintf_s(BufferName, L"SCP-Site Breach::Engine::Direct-X 12::Swap Chain Buffer[%i]", i);
        ReturnCode = D3D12SwapChainBuffers.at(i)->SetName(BufferName);
        if (ReturnCode != S_OK)
        {
            return ReturnCode;
        }
        D3D12Device->CreateRenderTargetView(D3D12SwapChainBuffers.at(i), nullptr, RTVDescriptorHandle);
        RTVDescriptorHandle.Offset(1, RTVDescriptorSize);
    }

    MSG WndMessage = { nullptr };

    IsRunning = true;

    D3D12_RESOURCE_BARRIER BackBufferResourceBarrier = {};
    BackBufferResourceBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
    BackBufferResourceBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
    BackBufferResourceBarrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
    const float clearColor[] = { 0.0f, 0.2f, 0.4f, 1.0f };
    CD3DX12_CPU_DESCRIPTOR_HANDLE dsvHandle(D3D12DSDescriptorHeap->GetCPUDescriptorHandleForHeapStart());

    while (IsRunning)
    {
        if (PeekMessageW(&WndMessage, m_GameWindow, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&WndMessage);
            DispatchMessageW(&WndMessage);
        }

        if (GetWindow(m_GameWindow, 0))
        {
            if (D3D12Fence->GetCompletedValue() < FenceValue)
            {
                D3D12Fence->SetEventOnCompletion(FenceValue, FenceEvent);
                WaitForSingleObject(FenceEvent, INFINITE);
            }
            CommandList.GetCommandAllocator()->Reset();
            D3D12CommandList->Reset(CommandList.GetCommandAllocator(), Pipeline.GetPipeline());
            FenceValue++;

            BackBufferResourceBarrier.Transition.pResource = D3D12SwapChainBuffers.at(DXGISwapChain->GetCurrentBackBufferIndex());
            BackBufferResourceBarrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
            BackBufferResourceBarrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
            D3D12CommandList->ResourceBarrier(1, &BackBufferResourceBarrier);
            CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(D3D12SwapChainDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), D3D12SwapChainBuffers.at(DXGISwapChain->GetCurrentBackBufferIndex()), D3D12Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV));
            D3D12CommandList->OMSetRenderTargets(1, &rtvHandle, FALSE, &dsvHandle);
            D3D12CommandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr);
            D3D12CommandList->ClearDepthStencilView(D3D12DSDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr);
            D3D12CommandList->SetGraphicsRootSignature(D3D12CommandQueue);
            BackBufferResourceBarrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
            BackBufferResourceBarrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
            D3D12CommandList->ResourceBarrier(1, &BackBufferResourceBarrier);
            D3D12CommandList->Close();
            D3D12CommandQueue->ExecuteCommandLists(1, reinterpret_cast<ID3D12CommandList**>(&D3D12CommandList));
            D3D12CommandQueue->Signal(D3D12Fence, FenceValue);
            DXGISwapChain->Present(0, 0);
        }
    }

    DXGISwapChain->SetFullscreenState(FALSE,  nullptr);
    DXGISwapChain->Release();
    D3D12SwapChainDescriptorHeap->Release();
    D3D12SwapChainBuffers.at(0)->Release();
    D3D12SwapChainBuffers.at(1)->Release();
    D3D12CommandList->Release();
    D3D12CommandAllocator->Release()
    D3D12CommandQueue->Release();
    D3D12PipelineStateObject->Release();
    D3D12CommandQueue->Release();
    CloseHandle(FenceEvent);
    D3D12Fence->Release();
    D3D12DSDescriptorHeap->Release();
    D3D12DS->Release();
    D3D12Device->Release();
#ifdef _SCPDebug
    D3D12DeviceDebugInfoQueue->Release();
#endif
    DXGIAdapter->Release();
    DXGIFactory->Release();
    D3D12DebugInterface->Release();
    DXGIDebugInfoQueue->Release();
    
    return 0;
}

Note: I converted this code from it's orginal format to this on keeping all of the settings and code. If something got messed up in the procress or converting it, it was a convertion error because this code worked fine except for the fact it was using both of my GPUs.

Edit: I forgot to mention which GPUs it was using. I have two GPUs. One is a GTX 1650, which is the one I want to use for all of my games, then I have a Intel UHD Graphics 630 (which is the GPU it wants to use) and it's my display driver. When I get the adapter and I get the description, it says it chooses my GTX, but when I look at task manager, it says it's using my display driver's 3D, and my GTX's 3D and copy. Does it have to do when I use "IDXGISwapChain::Present"?

Sammy
  • 41
  • 8
  • Without code that shows what you are doing - and a description of your hardware - anyone trying to help you would have to resort to guesswork. Also, since this question is quite specifically about DirectX, it is off-topic as C++. – Peter Jun 08 '22 at 02:46
  • Understood. But if would be a lot of code I would be sharing and it may confuse people. I will edit the question and put code in. – Sammy Jun 08 '22 at 02:56
  • In doing that, you might want to read up on how to provide a [mcve]. Which is a small but complete sample of code that illustrates your problem (and extraneous bits removed). In the process of producing such a sample, you might have an "Aha!" moment - and, if you don't, other folks have a better chance of being able to help. – Peter Jun 08 '22 at 03:03
  • Gotcha, I will put it in my question. – Sammy Jun 08 '22 at 03:06
  • I added my code. – Sammy Jun 08 '22 at 04:37

1 Answers1

1

You might have misunderstood what the 3D queue of your integrated GPU is doing.

It's not doing the rendering work, but it is handling the entire desktop composition workload. Which GPU that happens on is determined by where your monitor's framebuffer is located on.

The Taskmanager is misleading as far as you are concerned. It shows you which engine on the GPU side is active (and it shows active time only, no load indicator!), but not from which software side queue this workload was submitted. If you take a look with GPUView instead, you will most likely see it's workload submitted by WDM, not by your process. All usage percentages you see are also wrong, as they are not adjusted for dynamic clock speeds. Your iGPU might as well be in low-power-mode and still show an 80% utilization.

Just how much the internal GPU has to work depends on your swapchain configuration. All the windowed modes naturally result in a significantly higher overhead than the full screen modes (that includes borderless full-screen!), which shows in utilization.

Ext3h
  • 5,713
  • 17
  • 43
  • Thanks a lot! So, I'm not coding it wrong, it's just how Direct-X 12 works. – Sammy Jun 09 '22 at 10:26
  • @Sammy No, this is not "just how DirectX 12 works", this is how rendering works in general, DirectX 12 doesn't have anything to do with it. The adapter that you created your Command Queue on will be the one that does the work for your application. The iGPU renders anything else on your screen (like the Task Manager, for example), because the developer of these apps (eg Microsoft) decided so. And it also does the work of presenting the final image on the screen, because your screen is physically connected to that GPU. Your app only uses on Adapter, everything else is your OS and hardware setup. – Bizzarrus Jun 12 '22 at 15:21