tweak shared texture.
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -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<ID3D11Texture2D> SharedTextureWrapper::Get()
|
||||
{
|
||||
return pointer_;
|
||||
}
|
||||
|
||||
|
||||
Microsoft::WRL::ComPtr<ID3D11Texture2D> 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<SharedTextureWrapper>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,42 +96,42 @@ ComPtr<ID3D11Device> IsolatedD3D11Device::GetDevice()
|
||||
}
|
||||
|
||||
|
||||
ComPtr<ID3D11Texture2D> IsolatedD3D11Device::GetCompatibleSharedTexture(
|
||||
std::shared_ptr<SharedTextureWrapper> IsolatedD3D11Device::GetCompatibleSharedTexture(
|
||||
const ComPtr<ID3D11Texture2D>& 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;
|
||||
}
|
||||
@@ -1,10 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <d3d11.h>
|
||||
#include <wrl/client.h>
|
||||
|
||||
|
||||
// Shared texture wrapper to manager locking state
|
||||
class SharedTextureWrapper
|
||||
{
|
||||
friend class IsolatedD3D11Device;
|
||||
public:
|
||||
Microsoft::WRL::ComPtr<ID3D11Texture2D> Get();
|
||||
Microsoft::WRL::ComPtr<ID3D11Texture2D> Lock();
|
||||
void Unlock();
|
||||
bool IsLocked() const;
|
||||
|
||||
private:
|
||||
std::atomic<bool> locked_ = false;
|
||||
Microsoft::WRL::ComPtr<ID3D11Texture2D> pointer_;
|
||||
};
|
||||
|
||||
|
||||
// Thraed safe self created ID3D11Device from specified adapter
|
||||
class IsolatedD3D11Device
|
||||
{
|
||||
@@ -14,11 +32,11 @@ public:
|
||||
|
||||
HRESULT Create(const Microsoft::WRL::ComPtr<IDXGIAdapter>& adapter);
|
||||
Microsoft::WRL::ComPtr<ID3D11Device> GetDevice();
|
||||
Microsoft::WRL::ComPtr<ID3D11Texture2D> GetCompatibleSharedTexture(
|
||||
std::shared_ptr<SharedTextureWrapper> GetCompatibleSharedTexture(
|
||||
const Microsoft::WRL::ComPtr<ID3D11Texture2D>& src,
|
||||
UINT index);
|
||||
|
||||
private:
|
||||
Microsoft::WRL::ComPtr<ID3D11Device> device_;
|
||||
std::vector<Microsoft::WRL::ComPtr<ID3D11Texture2D>> cachedTextures_;
|
||||
std::vector<std::shared_ptr<SharedTextureWrapper>> cachedSharedTextures_;
|
||||
};
|
||||
|
||||
@@ -162,7 +162,12 @@ void Duplicator::Start()
|
||||
});
|
||||
|
||||
const auto timeout = static_cast<UINT>(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<IDXGIResource> 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<ID3D11Texture2D> 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<ID3D11DeviceContext> context;
|
||||
device_->GetDevice()->GetImmediateContext(&context);
|
||||
context->CopyResource(sharedTexture.Get(), texture.Get());
|
||||
@@ -325,14 +337,12 @@ bool Duplicator::Duplicate(UINT timeout)
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
lastFrame_ = Frame
|
||||
{
|
||||
frame_++,
|
||||
sharedTexture,
|
||||
lastFrameId_++,
|
||||
sharedTextureWrapper,
|
||||
frameInfo,
|
||||
metaData_
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -44,8 +44,8 @@ public:
|
||||
|
||||
struct Frame
|
||||
{
|
||||
UINT frame;
|
||||
Microsoft::WRL::ComPtr<ID3D11Texture2D> texture;
|
||||
UINT id;
|
||||
std::shared_ptr<class SharedTextureWrapper> 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<ID3D11Texture2D>& texture,
|
||||
@@ -82,7 +82,7 @@ private:
|
||||
std::shared_ptr<class IsolatedD3D11Device> device_;
|
||||
Microsoft::WRL::ComPtr<IDXGIOutputDuplication> dupl_;
|
||||
Frame lastFrame_;
|
||||
UINT frame_ = 0;
|
||||
UINT lastFrameId_ = 0;
|
||||
|
||||
volatile bool shouldRun_ = false;
|
||||
std::thread thread_;
|
||||
|
||||
@@ -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<ID3D11DeviceContext> context;
|
||||
GetDevice()->GetImmediateContext(&context);
|
||||
context->CopyResource(unityTexture_, texture.Get());
|
||||
context->CopyResource(unityTexture_, sharedTexture.Get());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@ private:
|
||||
MONITORINFOEX monitorInfo_;
|
||||
|
||||
std::shared_ptr<class Duplicator> duplicator_;
|
||||
UINT lastFrameId_ = -1;
|
||||
|
||||
ID3D11Texture2D* unityTexture_ = nullptr;
|
||||
Microsoft::WRL::ComPtr<ID3D11Texture2D> textureForGetPixels_;
|
||||
|
||||
Reference in New Issue
Block a user