ffmpeg-encoder/d3d11: Set highest eviction priority for buffers

This should ideally prevent textures from being removed from the GPU while the encoder is actively using them.
This commit is contained in:
Michael Fabian 'Xaymar' Dirks 2020-04-10 13:46:41 +02:00 committed by Michael Fabian Dirks
parent 771f41381e
commit c03fc933bb
1 changed files with 11 additions and 2 deletions

View File

@ -191,15 +191,20 @@ std::shared_ptr<AVFrame> d3d11_instance::allocate_frame(AVBufferRef* frames)
{ {
auto gctx = gs::context(); auto gctx = gs::context();
// Allocate a frame.
auto frame = std::shared_ptr<AVFrame>(av_frame_alloc(), [](AVFrame* frame) { auto frame = std::shared_ptr<AVFrame>(av_frame_alloc(), [](AVFrame* frame) {
av_frame_unref(frame); av_frame_unref(frame);
av_frame_free(&frame); av_frame_free(&frame);
}); });
// Create the necessary buffers.
if (av_hwframe_get_buffer(frames, frame.get(), 0) < 0) { if (av_hwframe_get_buffer(frames, frame.get(), 0) < 0) {
throw std::runtime_error("Failed to create AVFrame."); throw std::runtime_error("Failed to create AVFrame.");
} }
// Try to prevent this resource from ever leaving the GPU unless absolutely necessary.
reinterpret_cast<ID3D11Texture2D*>(frame->data[0])->SetEvictionPriority(DXGI_RESOURCE_PRIORITY_MAXIMUM);
return frame; return frame;
} }
@ -208,18 +213,20 @@ void d3d11_instance::copy_from_obs(AVBufferRef*, std::uint32_t handle, uint64_t
{ {
auto gctx = gs::context(); auto gctx = gs::context();
ATL::CComPtr<IDXGIKeyedMutex> mutex; // Attempt to acquire shared texture.
ATL::CComPtr<ID3D11Texture2D> input; ATL::CComPtr<ID3D11Texture2D> input;
if (FAILED(_device->OpenSharedResource(reinterpret_cast<HANDLE>(static_cast<uintptr_t>(handle)), if (FAILED(_device->OpenSharedResource(reinterpret_cast<HANDLE>(static_cast<uintptr_t>(handle)),
__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&input)))) { __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&input)))) {
throw std::runtime_error("Failed to open shared texture resource."); throw std::runtime_error("Failed to open shared texture resource.");
} }
// Attempt to acquire texture mutex.
ATL::CComPtr<IDXGIKeyedMutex> mutex;
if (FAILED(input->QueryInterface(__uuidof(IDXGIKeyedMutex), reinterpret_cast<void**>(&mutex)))) { if (FAILED(input->QueryInterface(__uuidof(IDXGIKeyedMutex), reinterpret_cast<void**>(&mutex)))) {
throw std::runtime_error("Failed to retrieve mutex for texture resource."); throw std::runtime_error("Failed to retrieve mutex for texture resource.");
} }
// Attempt to acquire texture lock.
if (FAILED(mutex->AcquireSync(lock_key, 1000))) { if (FAILED(mutex->AcquireSync(lock_key, 1000))) {
throw std::runtime_error("Failed to acquire lock on input texture."); throw std::runtime_error("Failed to acquire lock on input texture.");
} }
@ -234,10 +241,12 @@ void d3d11_instance::copy_from_obs(AVBufferRef*, std::uint32_t handle, uint64_t
// Restore original parameters on input. // Restore original parameters on input.
input->SetEvictionPriority(evict); input->SetEvictionPriority(evict);
// Release the acquired lock.
if (FAILED(mutex->ReleaseSync(lock_key))) { if (FAILED(mutex->ReleaseSync(lock_key))) {
throw std::runtime_error("Failed to release lock on input texture."); throw std::runtime_error("Failed to release lock on input texture.");
} }
// Release the lock on the next texture.
// TODO: Determine if this is necessary. // TODO: Determine if this is necessary.
mutex->ReleaseSync(*next_lock_key); mutex->ReleaseSync(*next_lock_key);
} }