mirror of
https://github.com/thinkonmay/sunshine-sdk.git
synced 2026-08-06 18:40:31 +00:00
wgc framepool buffer
This commit is contained in:
parent
d50b6ac0c2
commit
71b561b95e
@ -245,6 +245,10 @@ protected:
|
||||
std::chrono::milliseconds timeout, bool cursor_visible) = 0;
|
||||
virtual capture_e release_snapshot() = 0;
|
||||
virtual int complete_img(img_t *img, bool dummy) = 0;
|
||||
|
||||
// DDUP holds an unfair D3D11 device lock during AcquireNextFrame, which starves
|
||||
// the encoder thread on timeout. WGC doesn't have this problem.
|
||||
virtual bool needs_timeout_yield() const { return true; }
|
||||
};
|
||||
|
||||
class display_ram_t : public display_base_t {
|
||||
@ -391,6 +395,7 @@ public:
|
||||
std::shared_ptr<platf::img_t> &img_out, std::chrono::milliseconds timeout,
|
||||
bool cursor_visible) override;
|
||||
capture_e release_snapshot() override;
|
||||
bool needs_timeout_yield() const override { return false; }
|
||||
};
|
||||
|
||||
/**
|
||||
@ -405,5 +410,6 @@ public:
|
||||
std::shared_ptr<platf::img_t> &img_out, std::chrono::milliseconds timeout,
|
||||
bool cursor_visible) override;
|
||||
capture_e release_snapshot() override;
|
||||
bool needs_timeout_yield() const override { return false; }
|
||||
};
|
||||
} // namespace platf::dxgi
|
||||
|
||||
@ -256,24 +256,26 @@ capture_e display_base_t::capture(const push_captured_image_cb_t &push_captured_
|
||||
|
||||
frame_pacing_group_frames = 1;
|
||||
} else if (status == platf::capture_e::timeout) {
|
||||
// The D3D11 device is protected by an unfair lock that is held the entire time that
|
||||
// IDXGIOutputDuplication::AcquireNextFrame() is running. This is normally harmless,
|
||||
// however sometimes the encoding thread needs to interact with our ID3D11Device to
|
||||
// create dummy images or initialize the shared state that is used to pass textures
|
||||
// between the capture and encoding ID3D11Devices.
|
||||
//
|
||||
// When we're in a state where we're not actively receiving frames regularly, we will
|
||||
// spend almost 100% of our time in AcquireNextFrame() holding that critical lock.
|
||||
// Worse still, since it's unfair, we can monopolize it while the encoding thread
|
||||
// is starved. The encoding thread may acquire it for a few moments across a few
|
||||
// ID3D11Device calls before losing it again to us for another long time waiting in
|
||||
// AcquireNextFrame(). The starvation caused by this lock contention causes encoder
|
||||
// reinitialization to take several seconds instead of a fraction of a second.
|
||||
//
|
||||
// To avoid starving the encoding thread, sleep without the lock held for a little
|
||||
// while each time we reach our max frame timeout. This will only happen when nothing
|
||||
// is updating the display, so no visible stutter should be introduced by the sleep.
|
||||
timer->sleep_for(10ms);
|
||||
if (needs_timeout_yield()) {
|
||||
// The D3D11 device is protected by an unfair lock that is held the entire time that
|
||||
// IDXGIOutputDuplication::AcquireNextFrame() is running. This is normally harmless,
|
||||
// however sometimes the encoding thread needs to interact with our ID3D11Device to
|
||||
// create dummy images or initialize the shared state that is used to pass textures
|
||||
// between the capture and encoding ID3D11Devices.
|
||||
//
|
||||
// When we're in a state where we're not actively receiving frames regularly, we will
|
||||
// spend almost 100% of our time in AcquireNextFrame() holding that critical lock.
|
||||
// Worse still, since it's unfair, we can monopolize it while the encoding thread
|
||||
// is starved. The encoding thread may acquire it for a few moments across a few
|
||||
// ID3D11Device calls before losing it again to us for another long time waiting in
|
||||
// AcquireNextFrame(). The starvation caused by this lock contention causes encoder
|
||||
// reinitialization to take several seconds instead of a fraction of a second.
|
||||
//
|
||||
// To avoid starving the encoding thread, sleep without the lock held for a little
|
||||
// while each time we reach our max frame timeout. This will only happen when nothing
|
||||
// is updating the display, so no visible stutter should be introduced by the sleep.
|
||||
timer->sleep_for(10ms);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -127,7 +127,7 @@ int wgc_capture_t::init(display_base_t *display, const ::video::config_t &config
|
||||
frame_pool = winrt::Direct3D11CaptureFramePool::CreateFreeThreaded(
|
||||
uwp_device,
|
||||
static_cast<winrt::Windows::Graphics::DirectX::DirectXPixelFormat>(display->capture_format),
|
||||
2, item.Size());
|
||||
4, item.Size());
|
||||
capture_session = frame_pool.CreateCaptureSession(item);
|
||||
frame_pool.FrameArrived({this, &wgc_capture_t::on_frame_arrived});
|
||||
} catch (winrt::hresult_error &e) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user