From e0adedbc796f907d83ac3bf7c0b52cd46f17e566 Mon Sep 17 00:00:00 2001 From: Radu Grecu Date: Wed, 9 Oct 2024 21:07:10 +0200 Subject: [PATCH 1/3] AMD Display Capture --- .gitignore | 1 + cmake/compile_definitions/windows.cmake | 1 + src/platform/windows/display.h | 52 +++++ src/platform/windows/display_amd.cpp | 202 ++++++++++++++++++ src/platform/windows/display_base.cpp | 12 ++ src/platform/windows/display_vram.cpp | 92 ++++++++ src/video.cpp | 4 + .../assets/web/configs/tabs/Advanced.vue | 1 + 8 files changed, 365 insertions(+) create mode 100644 src/platform/windows/display_amd.cpp diff --git a/.gitignore b/.gitignore index 30818d52ae3..563b837d93e 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,7 @@ # VSCode IDE .vscode/ +.vs/ # build directories build/ diff --git a/cmake/compile_definitions/windows.cmake b/cmake/compile_definitions/windows.cmake index 7643d1d9efc..31c10aa18fd 100644 --- a/cmake/compile_definitions/windows.cmake +++ b/cmake/compile_definitions/windows.cmake @@ -51,6 +51,7 @@ set(PLATFORM_TARGET_FILES "${CMAKE_SOURCE_DIR}/src/platform/windows/display_vram.cpp" "${CMAKE_SOURCE_DIR}/src/platform/windows/display_ram.cpp" "${CMAKE_SOURCE_DIR}/src/platform/windows/display_wgc.cpp" + "${CMAKE_SOURCE_DIR}/src/platform/windows/display_amd.cpp" "${CMAKE_SOURCE_DIR}/src/platform/windows/audio.cpp" "${CMAKE_SOURCE_DIR}/third-party/ViGEmClient/src/ViGEmClient.cpp" "${CMAKE_SOURCE_DIR}/third-party/ViGEmClient/include/ViGEm/Client.h" diff --git a/src/platform/windows/display.h b/src/platform/windows/display.h index 3e035490394..331832c5b74 100644 --- a/src/platform/windows/display.h +++ b/src/platform/windows/display.h @@ -13,6 +13,8 @@ #include #include +#include +#include #include "src/platform/common.h" #include "src/utility.h" @@ -31,6 +33,13 @@ namespace platf::dxgi { dxgi->Release(); } + inline + void + FreeLibraryHelper(void *item) { + FreeLibrary((HMODULE) item); + } + + using hmodule_t = util::safe_ptr; using factory1_t = util::safe_ptr>; using dxgi_t = util::safe_ptr>; using dxgi1_t = util::safe_ptr>; @@ -177,6 +186,8 @@ namespace platf::dxgi { int height_before_rotation; int client_frame_rate; + int adapter_index; + int output_index; DXGI_FORMAT capture_format; D3D_FEATURE_LEVEL feature_level; @@ -429,4 +440,45 @@ namespace platf::dxgi { capture_e release_snapshot() override; }; + + class amd_capture_t { + + public: + amd_capture_t(); + ~amd_capture_t(); + + int + init(display_base_t *display, const ::video::config_t &config, int output_index); + capture_e + next_frame(std::chrono::milliseconds timeout, amf::AMFData** out); + capture_e + release_frame(); + + hmodule_t amfrt_lib; + amf_uint64 amf_version; + amf::AMFFactory *amf_factory; + + amf::AMFContextPtr context; + amf::AMFComponentPtr captureComp; + amf::AMFSurfacePtr capturedSurface; + amf_int64 capture_format; + AMFSize resolution; + }; + + + /** + * Display backend that uses Windows.Graphics.Capture with a hardware encoder. + */ + class display_amd_vram_t: public display_vram_t { + amd_capture_t dup; + + public: + int + init(const ::video::config_t &config, const std::string &display_name); + capture_e + snapshot(const pull_free_image_cb_t &pull_free_image_cb, std::shared_ptr &img_out, std::chrono::milliseconds timeout, bool cursor_visible) override; + capture_e + release_snapshot() override; + }; + } // namespace platf::dxgi diff --git a/src/platform/windows/display_amd.cpp b/src/platform/windows/display_amd.cpp new file mode 100644 index 00000000000..93a931b9f9a --- /dev/null +++ b/src/platform/windows/display_amd.cpp @@ -0,0 +1,202 @@ +/** + * @file src/platform/windows/display_amd.cpp + * @brief Display capture implementation using AMD Direct Capture + */ + +extern "C" { +#include +#include +} + +#include "display.h" +#include "misc.h" +#include "src/config.h" +#include "src/main.h" +#include "src/video.h" + +#include +#include +#include + +namespace platf { + using namespace std::literals; +} + +namespace platf::dxgi { + amd_capture_t::amd_capture_t() { + } + + amd_capture_t::~amd_capture_t() { + captureComp->Flush(); + captureComp->Terminate(); + context->Terminate(); + // capturedSurface = nullptr; + // free(context); + // free(captureComp); + // capturedSurface.Release(); + // free(capturedSurface); + } + + capture_e + amd_capture_t::release_frame() { + // BOOST_LOG(error) << "### R.G. release_frame, null pointer?: " << (capturedSurface == nullptr); + // if (capturedSurface != nullptr) + // { + // BOOST_LOG(error) << "### R.G. Releasing frame"; + // Sleep(10); + // capturedSurface->Release(); + // } + + return capture_e::ok; + } + + /** + * @brief Get the next frame from the producer thread. + * If not available, the capture thread blocks until one is, or the wait times out. + * @param timeout how long to wait for the next frame + * @param out a texture containing the frame just captured + * @param out_time the timestamp of the frame just captured + */ + capture_e + amd_capture_t::next_frame(std::chrono::milliseconds timeout, amf::AMFData** out) { + release_frame(); + // this CONSUMER runs in the capture thread + // Poll for the next frame + AMF_RESULT result; + auto capture_start = std::chrono::steady_clock::now(); + do { + result = captureComp->QueryOutput(out); + if (result == AMF_REPEAT) { + // Check for capture timeout expiration + if (std::chrono::steady_clock::now() - capture_start >= timeout) { + return platf::capture_e::timeout; + } + Sleep(1); + } + } while (result == AMF_REPEAT); + + if (result != AMF_OK) { + BOOST_LOG(error) << "DisplayCapture::QueryOutput() failed: "sv << result; + return capture_e::timeout; + } + return capture_e::ok; + } + + + int + amd_capture_t::init(display_base_t *display, const ::video::config_t &config, int output_index) { + // We have to load AMF before calling the base init() because we will need it loaded + // when our test_capture() function is called. + amfrt_lib.reset(LoadLibraryW(AMF_DLL_NAME)); + if (!amfrt_lib) { + // Probably not an AMD GPU system + return -1; + } + + auto fn_AMFQueryVersion = (AMFQueryVersion_Fn) GetProcAddress((HMODULE) amfrt_lib.get(), AMF_QUERY_VERSION_FUNCTION_NAME); + auto fn_AMFInit = (AMFInit_Fn) GetProcAddress((HMODULE) amfrt_lib.get(), AMF_INIT_FUNCTION_NAME); + + if (!fn_AMFQueryVersion || !fn_AMFInit) { + BOOST_LOG(error) << "Missing required AMF function!"sv; + return -1; + } + + auto result = fn_AMFQueryVersion(&amf_version); + if (result != AMF_OK) { + BOOST_LOG(error) << "AMFQueryVersion() failed: "sv << result; + return -1; + } + + // We don't support anything older than AMF 1.4.30. We'll gracefully fall back to DDAPI. + if (amf_version < AMF_MAKE_FULL_VERSION(1, 4, 30, 0)) { + BOOST_LOG(warning) << "AMD Direct Capture is not supported on AMF version"sv + << AMF_GET_MAJOR_VERSION(amf_version) << '.' + << AMF_GET_MINOR_VERSION(amf_version) << '.' + << AMF_GET_SUBMINOR_VERSION(amf_version) << '.' + << AMF_GET_BUILD_VERSION(amf_version); + BOOST_LOG(warning) << "Consider updating your AMD graphics driver for better capture performance!"sv; + return -1; + } + + // Initialize AMF library + result = fn_AMFInit(AMF_FULL_VERSION, &amf_factory); + if (result != AMF_OK) { + BOOST_LOG(error) << "AMFInit() failed: "sv << result; + return -1; + } + + DXGI_ADAPTER_DESC adapter_desc; + display->adapter->GetDesc(&adapter_desc); + + amf::AMFTrace* traceAMF; + amf_factory->GetTrace(&traceAMF); + traceAMF->SetGlobalLevel(AMF_TRACE_DEBUG); + traceAMF->EnableWriter(AMF_TRACE_WRITER_FILE, true); + traceAMF->SetWriterLevel(AMF_TRACE_WRITER_FILE, AMF_TRACE_DEBUG); + traceAMF->SetPath(L"D:/amflog.txt"); + + amf::AMFDebug* debugAMF; + amf_factory->GetDebug(&debugAMF); + debugAMF->AssertsEnable(false); + + // Bail if this is not an AMD GPU + if (adapter_desc.VendorId != 0x1002) { + return -1; + } + + // BOOST_LOG(info) << "### framerate " << config.framerate << " dynamicRange " << config.dynamicRange; + + // // FIXME: Don't use Direct Capture for a SDR P010 stream. The output is very dim. + // // This seems like a possible bug in VideoConverter when upconverting 8-bit to 10-bit. + // if (config.dynamicRange && !display->is_hdr()) { + // BOOST_LOG(info) << "AMD Direct Capture is disabled while 10-bit stream is in SDR mode"sv; + // return -1; + // } + + // Create the capture context + result = amf_factory->CreateContext(&context); + + if (result != AMF_OK) { + BOOST_LOG(error) << "CreateContext() failed: "sv << result; + return -1; + } + + // Associate the context with our ID3D11Device. This will enable multithread protection on the device. + result = context->InitDX11(display->device.get()); + if (result != AMF_OK) { + BOOST_LOG(error) << "InitDX11() failed: "sv << result; + return -1; + } + + display->capture_format = DXGI_FORMAT_UNKNOWN; + + // Create the DisplayCapture component + result = amf_factory->CreateComponent(context, AMFDisplayCapture, &(captureComp)); + if (result != AMF_OK) { + BOOST_LOG(error) << "CreateComponent(AMFDisplayCapture) failed: "sv << result; + return -1; + } + + // Set parameters for non-blocking capture + captureComp->SetProperty(AMF_DISPLAYCAPTURE_MONITOR_INDEX, output_index); + captureComp->SetProperty(AMF_DISPLAYCAPTURE_FRAMERATE, AMFConstructRate(0, 1)); + captureComp->SetProperty(AMF_DISPLAYCAPTURE_MODE, AMF_DISPLAYCAPTURE_MODE_GET_CURRENT_SURFACE); + captureComp->SetProperty(AMF_DISPLAYCAPTURE_DUPLICATEOUTPUT, true); + + // Initialize capture + result = captureComp->Init(amf::AMF_SURFACE_UNKNOWN, 0, 0); + if (result != AMF_OK) { + BOOST_LOG(error) << "DisplayCapture::Init() failed: "sv << result; + return -1; + } + + captureComp->GetProperty(AMF_DISPLAYCAPTURE_FORMAT, &(capture_format)); + captureComp->GetProperty(AMF_DISPLAYCAPTURE_RESOLUTION, &(resolution)); + BOOST_LOG(info) << "Desktop resolution ["sv << resolution.width << 'x' << resolution.height << ']'; + + BOOST_LOG(info) << "Using AMD Direct Capture API for display capture"sv; + + return 0; + } + +} // namespace platf::dxgi diff --git a/src/platform/windows/display_base.cpp b/src/platform/windows/display_base.cpp index d4731c0ec0b..4d22c28820c 100644 --- a/src/platform/windows/display_base.cpp +++ b/src/platform/windows/display_base.cpp @@ -565,6 +565,7 @@ namespace platf::dxgi { } if (desc.AttachedToDesktop && test_dxgi_duplication(adapter_tmp, output_tmp, false)) { + output_index = y; output = std::move(output_tmp); offset_x = desc.DesktopCoordinates.left; @@ -593,6 +594,7 @@ namespace platf::dxgi { } if (output) { + adapter_index = x; adapter = std::move(adapter_tmp); break; } @@ -1069,6 +1071,16 @@ namespace platf { } } + if (config::video.capture == "amd") { + if (hwdevice_type == mem_type_e::dxgi) { + auto disp = std::make_shared(); + + if (!disp->init(config, display_name)) { + return disp; + } + } + } + if (config::video.capture == "wgc" || config::video.capture.empty()) { if (hwdevice_type == mem_type_e::dxgi) { auto disp = std::make_shared(); diff --git a/src/platform/windows/display_vram.cpp b/src/platform/windows/display_vram.cpp index ba2b0685187..2e90d3d8c54 100644 --- a/src/platform/windows/display_vram.cpp +++ b/src/platform/windows/display_vram.cpp @@ -23,6 +23,7 @@ extern "C" { #include "src/video.h" #include +#include #include @@ -1629,6 +1630,97 @@ namespace platf::dxgi { return 0; } + + int + display_amd_vram_t::init(const ::video::config_t &config, const std::string &display_name) { + if (display_base_t::init(config, display_name) || dup.init(this, config, output_index)) + { + BOOST_LOG(error) << "AMD VRAM() failed"; + return -1; + } + + return 0; + } + + +/** + * @brief Get the next frame from the Windows.Graphics.Capture API and copy it into a new snapshot texture. + * @param pull_free_image_cb call this to get a new free image from the video subsystem. + * @param img_out the captured frame is returned here + * @param timeout how long to wait for the next frame + * @param cursor_visible whether to capture the cursor + */ + capture_e + display_amd_vram_t::snapshot(const pull_free_image_cb_t &pull_free_image_cb, std::shared_ptr &img_out, std::chrono::milliseconds timeout, bool cursor_visible) { + amf::AMFSurfacePtr output; + D3D11_TEXTURE2D_DESC desc; + + // Check for display configuration change + auto capture_status = dup.next_frame(timeout, (amf::AMFData **) &output); + if (capture_status != capture_e::ok) { + return capture_status; + } + dup.capturedSurface = output; + + // // Line below breaks reinit + // dup.capturedSurface->Acquire(); + + texture2d_t src = (ID3D11Texture2D*) dup.capturedSurface->GetPlaneAt(0)->GetNative(); + src->GetDesc(&desc); + + // It's possible for our display enumeration to race with mode changes and result in + // mismatched image pool and desktop texture sizes. If this happens, just reinit again. + if (desc.Width != width_before_rotation || desc.Height != height_before_rotation) { + BOOST_LOG(info) << "Capture size changed ["sv << width << 'x' << height << " -> "sv << desc.Width << 'x' << desc.Height << ']'; + return capture_e::reinit; + } + + // If we don't know the capture format yet, grab it from this texture + if (capture_format == DXGI_FORMAT_UNKNOWN) { + capture_format = desc.Format; + BOOST_LOG(info) << "AMD Capture format ["sv << dxgi_format_to_string(capture_format) << ']'; + } + + // It's also possible for the capture format to change on the fly. If that happens, + // reinitialize capture to try format detection again and create new images. + if (capture_format != desc.Format) { + BOOST_LOG(info) << "AMD Capture format changed ["sv << dxgi_format_to_string(capture_format) << " -> "sv << dxgi_format_to_string(desc.Format) << ']'; + return capture_e::reinit; + } + + std::shared_ptr img; + if (!pull_free_image_cb(img)) + return capture_e::interrupted; + + auto d3d_img = std::static_pointer_cast(img); + d3d_img->blank = false; // image is always ready for capture + if (complete_img(d3d_img.get(), false) == 0) { + texture_lock_helper lock_helper(d3d_img->capture_mutex.get()); + if (lock_helper.lock()) { + device_ctx->CopyResource(d3d_img->capture_texture.get(), src.get()); + } + else { + return capture_e::error; + } + } + else { + return capture_e::error; + } + img_out = img; + if (img_out) { + img_out->frame_timestamp = std::chrono::steady_clock::now(); + } + + src.release(); + return capture_e::ok; + } + + capture_e + display_amd_vram_t::release_snapshot() { + dup.release_frame(); + return capture_e::ok; + } + /** * Get the next frame from the Windows.Graphics.Capture API and copy it into a new snapshot texture. * @param pull_free_image_cb call this to get a new free image from the video subsystem. diff --git a/src/video.cpp b/src/video.cpp index 5f810860441..80d7487ba1a 100644 --- a/src/video.cpp +++ b/src/video.cpp @@ -709,6 +709,7 @@ namespace video { { "rc"s, &config::video.amd.amd_rc_av1 }, { "usage"s, &config::video.amd.amd_usage_av1 }, { "enforce_hrd"s, &config::video.amd.amd_enforce_hrd }, + { "loglevel"s, "debug"s}, }, {}, // SDR-specific options {}, // HDR-specific options @@ -734,6 +735,7 @@ namespace video { { "usage"s, &config::video.amd.amd_usage_hevc }, { "vbaq"s, &config::video.amd.amd_vbaq }, { "enforce_hrd"s, &config::video.amd.amd_enforce_hrd }, + { "loglevel"s, "debug"s}, }, {}, // SDR-specific options {}, // HDR-specific options @@ -757,6 +759,7 @@ namespace video { { "usage"s, &config::video.amd.amd_usage_h264 }, { "vbaq"s, &config::video.amd.amd_vbaq }, { "enforce_hrd"s, &config::video.amd.amd_enforce_hrd }, + { "loglevel"s, "debug"s}, }, {}, // SDR-specific options {}, // HDR-specific options @@ -1249,6 +1252,7 @@ namespace video { auto status = disp->capture(push_captured_image_callback, pull_free_image_callback, &display_cursor); + if (artificial_reinit && status != platf::capture_e::error) { status = platf::capture_e::reinit; diff --git a/src_assets/common/assets/web/configs/tabs/Advanced.vue b/src_assets/common/assets/web/configs/tabs/Advanced.vue index bd11adf2892..d5af93a8f5c 100644 --- a/src_assets/common/assets/web/configs/tabs/Advanced.vue +++ b/src_assets/common/assets/web/configs/tabs/Advanced.vue @@ -73,6 +73,7 @@ const config = ref(props.config) From 6f154df7fe151755095b85de1912872de9dd5bce Mon Sep 17 00:00:00 2001 From: Radu Grecu Date: Wed, 9 Oct 2024 20:29:31 +0200 Subject: [PATCH 2/3] AMD Display Capture reinit fix * Drain queued frames before termination --- src/platform/windows/display_amd.cpp | 35 +++++++++++++++------------ src/platform/windows/display_vram.cpp | 3 --- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/platform/windows/display_amd.cpp b/src/platform/windows/display_amd.cpp index 93a931b9f9a..6b58eeaec35 100644 --- a/src/platform/windows/display_amd.cpp +++ b/src/platform/windows/display_amd.cpp @@ -27,25 +27,30 @@ namespace platf::dxgi { } amd_capture_t::~amd_capture_t() { - captureComp->Flush(); + AMF_RESULT result; + + // Before terminating the Display Capture component, we need to drain the remaining frames + result = captureComp->Drain(); + if (result == AMF_OK) { + do { + result = captureComp->QueryOutput((amf::AMFData**) &capturedSurface); + Sleep(1); + } while (result != AMF_EOF); + } captureComp->Terminate(); + context->Terminate(); - // capturedSurface = nullptr; - // free(context); - // free(captureComp); - // capturedSurface.Release(); - // free(capturedSurface); + captureComp = nullptr; + context = nullptr; + capturedSurface = nullptr; } capture_e amd_capture_t::release_frame() { - // BOOST_LOG(error) << "### R.G. release_frame, null pointer?: " << (capturedSurface == nullptr); - // if (capturedSurface != nullptr) - // { - // BOOST_LOG(error) << "### R.G. Releasing frame"; - // Sleep(10); - // capturedSurface->Release(); - // } + if (capturedSurface != nullptr) + { + capturedSurface = nullptr; + } return capture_e::ok; } @@ -179,8 +184,8 @@ namespace platf::dxgi { // Set parameters for non-blocking capture captureComp->SetProperty(AMF_DISPLAYCAPTURE_MONITOR_INDEX, output_index); - captureComp->SetProperty(AMF_DISPLAYCAPTURE_FRAMERATE, AMFConstructRate(0, 1)); - captureComp->SetProperty(AMF_DISPLAYCAPTURE_MODE, AMF_DISPLAYCAPTURE_MODE_GET_CURRENT_SURFACE); + captureComp->SetProperty(AMF_DISPLAYCAPTURE_FRAMERATE, AMFConstructRate(config.framerate, 1)); + captureComp->SetProperty(AMF_DISPLAYCAPTURE_MODE, AMF_DISPLAYCAPTURE_MODE_WAIT_FOR_PRESENT); captureComp->SetProperty(AMF_DISPLAYCAPTURE_DUPLICATEOUTPUT, true); // Initialize capture diff --git a/src/platform/windows/display_vram.cpp b/src/platform/windows/display_vram.cpp index 2e90d3d8c54..60f3961bd0d 100644 --- a/src/platform/windows/display_vram.cpp +++ b/src/platform/windows/display_vram.cpp @@ -1662,9 +1662,6 @@ namespace platf::dxgi { } dup.capturedSurface = output; - // // Line below breaks reinit - // dup.capturedSurface->Acquire(); - texture2d_t src = (ID3D11Texture2D*) dup.capturedSurface->GetPlaneAt(0)->GetNative(); src->GetDesc(&desc); From 38763bb77a4ba00121d34438701c5dd7e18e9f93 Mon Sep 17 00:00:00 2001 From: Radu Grecu Date: Wed, 9 Oct 2024 21:04:02 +0200 Subject: [PATCH 3/3] AMD Display Capture documentation and fixes * Remove AMD Trace and debug statements * Add code comments --- src/platform/windows/display.h | 11 +++++++--- src/platform/windows/display_amd.cpp | 30 +++------------------------ src/platform/windows/display_base.cpp | 18 ++++++++-------- src/platform/windows/display_vram.cpp | 2 +- src/video.cpp | 1 - 5 files changed, 21 insertions(+), 41 deletions(-) diff --git a/src/platform/windows/display.h b/src/platform/windows/display.h index 331832c5b74..4e8e8aae76d 100644 --- a/src/platform/windows/display.h +++ b/src/platform/windows/display.h @@ -4,6 +4,8 @@ */ #pragma once +#include +#include #include #include #include @@ -13,8 +15,6 @@ #include #include -#include -#include #include "src/platform/common.h" #include "src/utility.h" @@ -33,6 +33,10 @@ namespace platf::dxgi { dxgi->Release(); } + /** + * Windows DLL loader function helper for AMD Display Capture + * @param item library dll + */ inline void FreeLibraryHelper(void *item) { @@ -467,7 +471,8 @@ namespace platf::dxgi { /** - * Display backend that uses Windows.Graphics.Capture with a hardware encoder. + * Display backend that uses AMD Display Capture with a hardware encoder. + * Main purpose is to capture AMD Fluid Motion Frames (AFMF) */ class display_amd_vram_t: public display_vram_t { amd_capture_t dup; diff --git a/src/platform/windows/display_amd.cpp b/src/platform/windows/display_amd.cpp index 6b58eeaec35..c497b7b3f85 100644 --- a/src/platform/windows/display_amd.cpp +++ b/src/platform/windows/display_amd.cpp @@ -55,24 +55,21 @@ namespace platf::dxgi { return capture_e::ok; } - /** + /** * @brief Get the next frame from the producer thread. * If not available, the capture thread blocks until one is, or the wait times out. * @param timeout how long to wait for the next frame - * @param out a texture containing the frame just captured - * @param out_time the timestamp of the frame just captured + * @param out pointer to AMFSurfacePtr */ capture_e amd_capture_t::next_frame(std::chrono::milliseconds timeout, amf::AMFData** out) { release_frame(); - // this CONSUMER runs in the capture thread - // Poll for the next frame + AMF_RESULT result; auto capture_start = std::chrono::steady_clock::now(); do { result = captureComp->QueryOutput(out); if (result == AMF_REPEAT) { - // Check for capture timeout expiration if (std::chrono::steady_clock::now() - capture_start >= timeout) { return platf::capture_e::timeout; } @@ -81,7 +78,6 @@ namespace platf::dxgi { } while (result == AMF_REPEAT); if (result != AMF_OK) { - BOOST_LOG(error) << "DisplayCapture::QueryOutput() failed: "sv << result; return capture_e::timeout; } return capture_e::ok; @@ -133,31 +129,11 @@ namespace platf::dxgi { DXGI_ADAPTER_DESC adapter_desc; display->adapter->GetDesc(&adapter_desc); - amf::AMFTrace* traceAMF; - amf_factory->GetTrace(&traceAMF); - traceAMF->SetGlobalLevel(AMF_TRACE_DEBUG); - traceAMF->EnableWriter(AMF_TRACE_WRITER_FILE, true); - traceAMF->SetWriterLevel(AMF_TRACE_WRITER_FILE, AMF_TRACE_DEBUG); - traceAMF->SetPath(L"D:/amflog.txt"); - - amf::AMFDebug* debugAMF; - amf_factory->GetDebug(&debugAMF); - debugAMF->AssertsEnable(false); - // Bail if this is not an AMD GPU if (adapter_desc.VendorId != 0x1002) { return -1; } - // BOOST_LOG(info) << "### framerate " << config.framerate << " dynamicRange " << config.dynamicRange; - - // // FIXME: Don't use Direct Capture for a SDR P010 stream. The output is very dim. - // // This seems like a possible bug in VideoConverter when upconverting 8-bit to 10-bit. - // if (config.dynamicRange && !display->is_hdr()) { - // BOOST_LOG(info) << "AMD Direct Capture is disabled while 10-bit stream is in SDR mode"sv; - // return -1; - // } - // Create the capture context result = amf_factory->CreateContext(&context); diff --git a/src/platform/windows/display_base.cpp b/src/platform/windows/display_base.cpp index 4d22c28820c..61690877488 100644 --- a/src/platform/windows/display_base.cpp +++ b/src/platform/windows/display_base.cpp @@ -1054,26 +1054,26 @@ namespace platf { */ std::shared_ptr display(mem_type_e hwdevice_type, const std::string &display_name, const video::config_t &config) { - if (config::video.capture == "ddx" || config::video.capture.empty()) { + if (config::video.capture == "amd" || config::video.capture.empty()) { if (hwdevice_type == mem_type_e::dxgi) { - auto disp = std::make_shared(); + auto disp = std::make_shared(); if (!disp->init(config, display_name)) { return disp; } } - else if (hwdevice_type == mem_type_e::system) { - auto disp = std::make_shared(); + } + + if (config::video.capture == "ddx" || config::video.capture.empty()) { + if (hwdevice_type == mem_type_e::dxgi) { + auto disp = std::make_shared(); if (!disp->init(config, display_name)) { return disp; } } - } - - if (config::video.capture == "amd") { - if (hwdevice_type == mem_type_e::dxgi) { - auto disp = std::make_shared(); + else if (hwdevice_type == mem_type_e::system) { + auto disp = std::make_shared(); if (!disp->init(config, display_name)) { return disp; diff --git a/src/platform/windows/display_vram.cpp b/src/platform/windows/display_vram.cpp index 60f3961bd0d..6fc75017f03 100644 --- a/src/platform/windows/display_vram.cpp +++ b/src/platform/windows/display_vram.cpp @@ -1643,7 +1643,7 @@ namespace platf::dxgi { } -/** + /** * @brief Get the next frame from the Windows.Graphics.Capture API and copy it into a new snapshot texture. * @param pull_free_image_cb call this to get a new free image from the video subsystem. * @param img_out the captured frame is returned here diff --git a/src/video.cpp b/src/video.cpp index 80d7487ba1a..5477dabbbde 100644 --- a/src/video.cpp +++ b/src/video.cpp @@ -1252,7 +1252,6 @@ namespace video { auto status = disp->capture(push_captured_image_callback, pull_free_image_callback, &display_cursor); - if (artificial_reinit && status != platf::capture_e::error) { status = platf::capture_e::reinit;