diff --git a/Assets/uDesktopDuplication/Plugins/x86/uDesktopDuplication.dll b/Assets/uDesktopDuplication/Plugins/x86/uDesktopDuplication.dll index b1e3148..7800cdc 100644 Binary files a/Assets/uDesktopDuplication/Plugins/x86/uDesktopDuplication.dll and b/Assets/uDesktopDuplication/Plugins/x86/uDesktopDuplication.dll differ diff --git a/Assets/uDesktopDuplication/Plugins/x86_64/uDesktopDuplication.dll b/Assets/uDesktopDuplication/Plugins/x86_64/uDesktopDuplication.dll index 4a4bc9c..899ea9b 100644 Binary files a/Assets/uDesktopDuplication/Plugins/x86_64/uDesktopDuplication.dll and b/Assets/uDesktopDuplication/Plugins/x86_64/uDesktopDuplication.dll differ diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/Device.cpp b/Plugins/uDesktopDuplication/uDesktopDuplication/Device.cpp index 01240e7..435300c 100644 --- a/Plugins/uDesktopDuplication/uDesktopDuplication/Device.cpp +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/Device.cpp @@ -7,6 +7,7 @@ #include "IUnityGraphicsD3D11.h" #include "Device.h" #include "Debug.h" +#include "Common.h" #pragma comment(lib, "d3d11.lib") @@ -14,9 +15,39 @@ using namespace Microsoft::WRL; -IsolatedD3D11Device::IsolatedD3D11Device(UINT cachedTextureNum) - : cachedTextures_(cachedTextureNum) +Microsoft::WRL::ComPtr SharedTextureWrapper::Get() { + return pointer_; +} + + +Microsoft::WRL::ComPtr SharedTextureWrapper::Lock() +{ + if (locked_) return nullptr; + locked_ = true; + return pointer_; +} + + +void SharedTextureWrapper::Unlock() +{ + locked_ = false; +} + + +bool SharedTextureWrapper::IsLocked() const +{ + return locked_; +} + + + +IsolatedD3D11Device::IsolatedD3D11Device(UINT cachedTextureNum) +{ + for (UINT i = 0; i < cachedTextureNum; ++i) + { + cachedSharedTextures_.push_back(std::make_shared()); + } } @@ -65,42 +96,42 @@ ComPtr IsolatedD3D11Device::GetDevice() } -ComPtr IsolatedD3D11Device::GetCompatibleSharedTexture( +std::shared_ptr IsolatedD3D11Device::GetCompatibleSharedTexture( const ComPtr& src, UINT index) { - if (index < 0 || index >= cachedTextures_.size()) + if (index < 0 || index >= cachedSharedTextures_.size()) { Debug::Error("IsolatedD3D11Device::GetCompatibleSharedTexture() => ", index, " is out of cachedTextures range."); return nullptr; } - auto& cachedTexture = cachedTextures_.at(index); - - D3D11_TEXTURE2D_DESC srcDesc; - src->GetDesc(&srcDesc); + auto& sharedTextureWrapper = cachedSharedTextures_.at(index); + auto& texture = sharedTextureWrapper->pointer_; // raw pointer // check if the format and size of the current texture are same as the source one - if (cachedTexture) + D3D11_TEXTURE2D_DESC srcDesc; + src->GetDesc(&srcDesc); + if (texture) { D3D11_TEXTURE2D_DESC targetDesc; - cachedTexture->GetDesc(&targetDesc); + texture->GetDesc(&targetDesc); if (targetDesc.Format == srcDesc.Format && targetDesc.Width == srcDesc.Width && targetDesc.Height == srcDesc.Height) { - return cachedTexture; + return sharedTextureWrapper; } } // for sharing this texture with unity device srcDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED; - if (FAILED(device_->CreateTexture2D(&srcDesc, nullptr, &cachedTexture))) + if (FAILED(device_->CreateTexture2D(&srcDesc, nullptr, &texture))) { Debug::Error("IsolatedD3D11Device::GetCompatibleSharedTexture() => Creating shared texture failed."); return nullptr; } - return cachedTexture; + return sharedTextureWrapper; } \ No newline at end of file diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/Device.h b/Plugins/uDesktopDuplication/uDesktopDuplication/Device.h index 70db375..fbcfcd0 100644 --- a/Plugins/uDesktopDuplication/uDesktopDuplication/Device.h +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/Device.h @@ -1,10 +1,28 @@ #pragma once +#include #include +#include #include #include +// Shared texture wrapper to manager locking state +class SharedTextureWrapper +{ +friend class IsolatedD3D11Device; +public: + Microsoft::WRL::ComPtr Get(); + Microsoft::WRL::ComPtr Lock(); + void Unlock(); + bool IsLocked() const; + +private: + std::atomic locked_ = false; + Microsoft::WRL::ComPtr pointer_; +}; + + // Thraed safe self created ID3D11Device from specified adapter class IsolatedD3D11Device { @@ -14,11 +32,11 @@ public: HRESULT Create(const Microsoft::WRL::ComPtr& adapter); Microsoft::WRL::ComPtr GetDevice(); - Microsoft::WRL::ComPtr GetCompatibleSharedTexture( + std::shared_ptr GetCompatibleSharedTexture( const Microsoft::WRL::ComPtr& src, UINT index); private: Microsoft::WRL::ComPtr device_; - std::vector> cachedTextures_; + std::vector> cachedSharedTextures_; }; diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/Duplicator.cpp b/Plugins/uDesktopDuplication/uDesktopDuplication/Duplicator.cpp index fff0fd3..8752844 100644 --- a/Plugins/uDesktopDuplication/uDesktopDuplication/Duplicator.cpp +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/Duplicator.cpp @@ -162,7 +162,12 @@ void Duplicator::Start() }); const auto timeout = static_cast(frameMilliSeconds); - if (!Duplicate(timeout)) break; + Duplicate(timeout); + + if (state_ != State::Running) + { + break; + } } if (state_ == State::Running) @@ -229,9 +234,9 @@ const Duplicator::Frame& Duplicator::GetLastFrame() const } -bool Duplicator::Duplicate(UINT timeout) +void Duplicator::Duplicate(UINT timeout) { - if (!dupl_ || !device_) return false; + if (!dupl_ || !device_) return; ComPtr resource; DXGI_OUTDUPL_FRAME_INFO frameInfo; @@ -247,31 +252,32 @@ bool Duplicator::Duplicate(UINT timeout) // it is necessary to re-initialize monitors. Debug::Log("Duplicator::Duplicate() => DXGI_ERROR_ACCESS_LOST."); state_ = State::AccessLost; - return false; + break; } case DXGI_ERROR_WAIT_TIMEOUT: { // This often occurs when timeout value is small and it is not problem. // Debug::Log("Duplicator::Duplicate() => DXGI_ERROR_WAIT_TIMEOUT."); - return true; + break; } case DXGI_ERROR_INVALID_CALL: { Debug::Error("Duplicator::Duplicate() => DXGI_ERROR_INVALID_CALL."); - return false; + break; } case E_INVALIDARG: { Debug::Error("Duplicator::Duplicate() => E_INVALIDARG."); - return false; + break; } default: { state_ = State::Unknown; Debug::Error("Duplicator::Duplicate() => Unknown Error."); - return false; + break; } } + return; } ScopedReleaser releaser([this] @@ -305,15 +311,21 @@ bool Duplicator::Duplicate(UINT timeout) ComPtr texture; if (FAILED(resource.As(&texture))) { - return false; + Debug::Error("Duplicator::Duplicate() => IDXGIResource could not be converted to ID3D11Texture2D."); + return; } - auto sharedTexture = device_->GetCompatibleSharedTexture(texture, frame_ % 2); - if (!sharedTexture) + auto sharedTextureWrapper = device_->GetCompatibleSharedTexture(texture, lastFrameId_ % 2); + if (!sharedTextureWrapper) { - return false; + Debug::Error("Duplicator::Duplicate() => Shared texture is null."); + return; } + auto sharedTexture = sharedTextureWrapper->Lock(); + if (!sharedTexture) return; + ScopedReleaser sharedTextureReleaser([&] { sharedTextureWrapper->Unlock(); }); + ComPtr context; device_->GetDevice()->GetImmediateContext(&context); context->CopyResource(sharedTexture.Get(), texture.Get()); @@ -325,14 +337,12 @@ bool Duplicator::Duplicate(UINT timeout) std::lock_guard lock(mutex_); lastFrame_ = Frame { - frame_++, - sharedTexture, + lastFrameId_++, + sharedTextureWrapper, frameInfo, metaData_ - }; + }; } - - return true; } diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/Duplicator.h b/Plugins/uDesktopDuplication/uDesktopDuplication/Duplicator.h index 66a7040..b52d361 100644 --- a/Plugins/uDesktopDuplication/uDesktopDuplication/Duplicator.h +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/Duplicator.h @@ -44,8 +44,8 @@ public: struct Frame { - UINT frame; - Microsoft::WRL::ComPtr texture; + UINT id; + std::shared_ptr texture; DXGI_OUTDUPL_FRAME_INFO info; Metadata metaData; }; @@ -67,7 +67,7 @@ private: void InitializeDuplication(); void CheckUnityAdapter(); - bool Duplicate(UINT timeout); + void Duplicate(UINT timeout); void UpdateCursor( const Microsoft::WRL::ComPtr& texture, @@ -82,7 +82,7 @@ private: std::shared_ptr device_; Microsoft::WRL::ComPtr dupl_; Frame lastFrame_; - UINT frame_ = 0; + UINT lastFrameId_ = 0; volatile bool shouldRun_ = false; std::thread thread_; diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/Monitor.cpp b/Plugins/uDesktopDuplication/uDesktopDuplication/Monitor.cpp index 0c719f4..8abe933 100644 --- a/Plugins/uDesktopDuplication/uDesktopDuplication/Monitor.cpp +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/Monitor.cpp @@ -71,15 +71,19 @@ void Monitor::Finalize() void Monitor::Render() { const auto& frame = duplicator_->GetLastFrame(); - const auto& texture = frame.texture; - if (!texture) return; + if (frame.id == lastFrameId_) return; + lastFrameId_ = frame.id; + + const auto& sharedTextureWrapper = frame.texture; + auto sharedTexture = sharedTextureWrapper->Lock(); + if (!sharedTexture) return; + ScopedReleaser releaser([&] { sharedTextureWrapper->Unlock(); }); - // Get texture if (unityTexture_) { D3D11_TEXTURE2D_DESC srcDesc, dstDesc; - texture->GetDesc(&srcDesc); + sharedTexture->GetDesc(&srcDesc); unityTexture_->GetDesc(&dstDesc); if (srcDesc.Width != dstDesc.Width || srcDesc.Height != dstDesc.Height) @@ -93,7 +97,7 @@ void Monitor::Render() { ComPtr context; GetDevice()->GetImmediateContext(&context); - context->CopyResource(unityTexture_, texture.Get()); + context->CopyResource(unityTexture_, sharedTexture.Get()); } } diff --git a/Plugins/uDesktopDuplication/uDesktopDuplication/Monitor.h b/Plugins/uDesktopDuplication/uDesktopDuplication/Monitor.h index e5e4439..d6637d2 100644 --- a/Plugins/uDesktopDuplication/uDesktopDuplication/Monitor.h +++ b/Plugins/uDesktopDuplication/uDesktopDuplication/Monitor.h @@ -70,6 +70,7 @@ private: MONITORINFOEX monitorInfo_; std::shared_ptr duplicator_; + UINT lastFrameId_ = -1; ID3D11Texture2D* unityTexture_ = nullptr; Microsoft::WRL::ComPtr textureForGetPixels_;