Coder Social home page Coder Social logo

Comments (12)

Xaymar avatar Xaymar commented on June 12, 2024

Example Setup:

  • AMD R9 285
  • AMD RX 480 (Primary)

No matter what I do, I can't use the features of the R9 285. The R9 285 is capable of B-Pictures, but GetCaps() only reports the capabilities of the RX 480.

Edit: This is especially important for "AMD Hybrid" (Switchable GPU) systems, where GetCaps will report that encoding is not supported, but the GPU definitely can do encoding.

from amf.

GeoffPark avatar GeoffPark commented on June 12, 2024

You should be able to call DXGIFactory::EnumAdapters to enumerate all your adapters, then pass the selected one to D3D11CreateDevice to create a device that you can use to get the correct caps.

See:

https://msdn.microsoft.com/en-us/library/windows/desktop/bb174538(v=vs.85).aspx
and
https://msdn.microsoft.com/en-us/library/windows/desktop/ff476082(v=vs.85).aspx

-Geoff

From: Michael Fabian Dirks [mailto:[email protected]]
Sent: Tuesday, November 15, 2016 8:46 AM
To: GPUOpen-LibrariesAndSDKs/AMF [email protected]
Subject: [GPUOpen-LibrariesAndSDKs/AMF] Video Encode API: Querying Capabilities for other Devices in the system? (#42)

I'm trying to add proper multi-GPU support to my plugin, but currently fail to actually do this. My attempt right now is to create a DirectX11/DirectX9/OpenGL device, initialize the amf::AMFContext with it (InitDX11/InitDX9/InitOpenGL) and then use CreateComponent and GetCaps to get the device capabilities.

This doesn't work as expected, as it will always output the capabilities of the primary GPU - which is not what I need or want.

Is there an example that shows how to do this properly? Or is this not yet possible?


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHubhttps://github.com//issues/42, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AP4h_IgosAnIACdKGqHsItj_vlgqk4Ajks5q-bexgaJpZM4KyisX.

from amf.

Xaymar avatar Xaymar commented on June 12, 2024

That's what I am currently doing, however GetCaps still only reports capabilities for the primary GPU.

from amf.

MikhailAMD avatar MikhailAMD commented on June 12, 2024

Here is slightly modified CapabilityManager sample that goes through all GPUs. I inserted Fury and RX 480 in the same machine. The sample reported the correct B-frame support for both boards: one ON one OFF. Please try.
CapabilityManager.zip

from amf.

Xaymar avatar Xaymar commented on June 12, 2024

That one works, thanks. I'll have to see what is missing in my code to make it work.

from amf.

Xaymar avatar Xaymar commented on June 12, 2024

Perhaps you can see what I'm doing wrong, because I'm kinda stuck now. I create a Direct3D 11.1/11.0 instance on the necessary adapter, call InitDX11 with it, and then continue from there to query the device capabilities. This is the code:

        amf::AMFContextPtr amfContext;
        res = amfFactory->CreateContext(&amfContext);
        if (res != AMF_OK) {
            AMF_LOG_ERROR("Unable to gather capabilities for device '%s', error %ls (code %d).",
                device.Name.c_str(), amfInstance->GetTrace()->GetResultText(res), res);
            continue;
        }

        Plugin::API::BaseAPI apiDev = Plugin::API::BaseAPI::CreateBestAvailableAPIForDevice(device);
        switch (apiDev.GetType()) {
            case Plugin::API::APIType_Direct3D11:
                res = amfContext->InitDX11(apiDev.GetContext());
                break;
            case Plugin::API::APIType_Direct3D9:
                res = amfContext->InitDX9(apiDev.GetContext());
                break;
            case Plugin::API::APIType_OpenGL:
                res = amfContext->InitOpenGL(apiDev.GetContext(), nullptr, nullptr);
                break;
        }
        if (res != AMF_OK) {
            AMF_LOG_ERROR("Unable to gather capabilities for device '%s' after initialization, error %ls (code %d).",
                device.Name.c_str(), amfInstance->GetTrace()->GetResultText(res), res);
            continue;
        }
amf::AMFContextPtr amfContext;res = amfFactory->CreateContext(&amfContext);if (res != AMF_OK) {AMF_LOG_ERROR("Unable to gather capabilities for device '%s', error %ls (code %d).",device.Name.c_str(), amfInstance->GetTrace()->GetResultText(res), res);continue;}Plugin::API::BaseAPI apiDev = Plugin::API::BaseAPI::CreateBestAvailableAPIForDevice(device);switch (apiDev.GetType()) {case Plugin::API::APIType_Direct3D11:res = amfContext->InitDX11(apiDev.GetContext());break;case Plugin::API::APIType_Direct3D9:res = amfContext->InitDX9(apiDev.GetContext());break;case Plugin::API::APIType_OpenGL:res = amfContext->InitOpenGL(apiDev.GetContext(), nullptr, nullptr);break;}if (res != AMF_OK) {AMF_LOG_ERROR("Unable to gather capabilities for device '%s' after initialization, error %ls (code %d).",device.Name.c_str(), amfInstance->GetTrace()->GetResultText(res), res);continue;}

apiDev.GetContext() returns a IDirect3D11* pointer for the adapter. Does AMF expect something special here? I saw that the modified capability manager uses ATL::CComPtr instead.

This is the code that creates the IDirect3D11 pointer:

            D3D_FEATURE_LEVEL featureLevels[] = {
                D3D_FEATURE_LEVEL_11_1,
                D3D_FEATURE_LEVEL_11_0
            };
            D3D_FEATURE_LEVEL featureLevel;
            uint32_t flags = 
                D3D11_CREATE_DEVICE_BGRA_SUPPORT |
                D3D11_CREATE_DEVICE_DISABLE_GPU_TIMEOUT |
                D3D11_CREATE_DEVICE_VIDEO_SUPPORT;

            auto singletonD3D11 = SingletonD3D11::GetInstance();
            HRESULT hr = singletonD3D11->D3D11CreateDevice(
                pAdapter, pAdapter == NULL ? D3D_DRIVER_TYPE_HARDWARE : D3D_DRIVER_TYPE_UNKNOWN,
                NULL, flags,
                featureLevels, _countof(featureLevels),
                D3D11_SDK_VERSION,
                &pDevice, &featureLevel, &pDeviceContext);
            if (FAILED(hr)) {
                AMF_LOG_ERROR("Unable to create D3D11.1 device.");
                hr = singletonD3D11->D3D11CreateDevice(
                    pAdapter, pAdapter == NULL ? D3D_DRIVER_TYPE_HARDWARE : D3D_DRIVER_TYPE_UNKNOWN,
                    NULL, flags,
                    featureLevels + 1, _countof(featureLevels) - 1,
                    D3D11_SDK_VERSION,
                    &pDevice, &featureLevel, &pDeviceContext);
                if (FAILED(hr)) {
                    throw new std::exception("Unable to create D3D11 device.");
                }
            }

from amf.

MikhailAMD avatar MikhailAMD commented on June 12, 2024

The calls to AMF look correct. I would verify adapter just before calling InitDX11() :

  • Get pointer to ID3D11Device from appDev,
  • Query for IDXGIDevice interface
  • call dxgiDevice->GetAdapter()
  • call adapter->GetDesc()
  • trace DXGI_ADAPTER_DESC::AdapterLuid which is DWORD and LONG
  • trace for different device and compare LUIDs

LUIDs is really unique adapter ID for current Windows session. It may give you Idea if you get the correct D3D11Device

from amf.

Xaymar avatar Xaymar commented on June 12, 2024

I've added that debug code, though it only revealed that the Direct3D11Device* is on the correct Adapter. Question remains why GetCaps only reports for the primary GPU in the plugin, but works fine in CapabilityManager. I hope this is not a limitation of it running in a dll.

Debug Output:

[AMF Encoder] Radeon (TM) RX 480 Graphics, 0:346269
[AMF Encoder] AMD Radeon R9 200 Series, 0:349276
[AMF Encoder] 0:346269 // pAdapter->GetDesc()->AdapterLuid
[AMF Encoder] 0:346269 // DXGIDevice->GetAdapter()->GetDesc()->AdapterLuid
[AMF Encoder] <Plugin::AMD::VCECapabilities::Refresh> Failed to gather capabilities for device 'Radeon (TM) RX 480 Graphics' with codec 'AMFVideoEncoderHW_HEVC', error AMF_NOT_SUPPORTED (code 10).
[AMF Encoder] 0:349276 // pAdapter->GetDesc()->AdapterLuid
[AMF Encoder] 0:349276 // DXGIDevice->GetAdapter()->GetDesc()->AdapterLuid
[AMF Encoder] <Plugin::AMD::VCECapabilities::Refresh> Failed to gather capabilities for device 'AMD Radeon R9 200 Series' with codec 'AMFVideoEncoderHW_HEVC', error AMF_NOT_SUPPORTED (code 10).

I've updated the master branch to include the new changes now: https://github.com/Xaymar/obs-studio_amf-encoder-plugin/tree/master

from amf.

MikhailAMD avatar MikhailAMD commented on June 12, 2024

I checked code in the plug-in master. The AMF CAPS are acquired in a different AMF context and different AMF component on default DX device: Plugin::AMD::VCECapabilities::RefreshCapabilities()
Am I missing something here?

from amf.

Xaymar avatar Xaymar commented on June 12, 2024

That's odd, RefreshCapabilities() only exists in stable and unstable, in master I've rewritten most of the code for multi GPU support. Make sure that when checking out the code that you tell git to pull the master branch. Here are the files and how they should look like:

  1. https://github.com/Xaymar/obs-studio_amf-encoder-plugin/blob/master/Source/amd-amf-vce-capabilities.cpp
  2. https://github.com/Xaymar/obs-studio_amf-encoder-plugin/blob/master/Source/api-d3d11.cpp

And the expected call structure:

(for each device do:)

(for each codec do:)

from amf.

MikhailAMD avatar MikhailAMD commented on June 12, 2024

I debugged the plug-in and found the problem. Replace the line from commented out one to the next line:
// res = amfContext->InitDX11(apiDev.GetContext());
res = amfContext->InitDX11(apiDev.GetContext(), amf::AMF_DX11_1);
By default DX11_0 doesn't support video and DX11_1 does. For example allocation of NV12 surface is available in DX11_1 only. So the second parameter tells AMF which one to use. I will check if I could make AMF more flexible in the future.

from amf.

Xaymar avatar Xaymar commented on June 12, 2024

Found the actual cause, BaseAPI wasn't actually being overridden so GetContext() always returned nullptr. With that and your fix it works.

from amf.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.