prepare multiple texture buffer for each device to avoid flickering cursor #11

This commit is contained in:
hecomi
2017-01-06 17:29:09 +09:00
parent 6bd892bc4b
commit 0634993bb0
7 changed files with 49 additions and 22 deletions
@@ -14,7 +14,8 @@ using namespace Microsoft::WRL;
IsolatedD3D11Device::IsolatedD3D11Device() IsolatedD3D11Device::IsolatedD3D11Device(UINT cachedTextureNum)
: cachedTextures_(cachedTextureNum)
{ {
} }
@@ -64,33 +65,42 @@ ComPtr<ID3D11Device> IsolatedD3D11Device::GetDevice()
} }
ComPtr<ID3D11Texture2D> IsolatedD3D11Device::GetCompatibleSharedTexture(const ComPtr<ID3D11Texture2D>& src) ComPtr<ID3D11Texture2D> IsolatedD3D11Device::GetCompatibleSharedTexture(
const ComPtr<ID3D11Texture2D>& src,
UINT index)
{ {
if (index < 0 || index >= cachedTextures_.size())
{
Debug::Error("IsolatedD3D11Device::GetCompatibleSharedTexture() => ", index, " is out of cachedTextures range.");
return nullptr;
}
auto& cachedTexture = cachedTextures_.at(index);
D3D11_TEXTURE2D_DESC srcDesc; D3D11_TEXTURE2D_DESC srcDesc;
src->GetDesc(&srcDesc); src->GetDesc(&srcDesc);
// check if the format and size of the current texture are same as the source one // check if the format and size of the current texture are same as the source one
if (cachedTexture_) if (cachedTexture)
{ {
D3D11_TEXTURE2D_DESC targetDesc; D3D11_TEXTURE2D_DESC targetDesc;
cachedTexture_->GetDesc(&targetDesc); cachedTexture->GetDesc(&targetDesc);
if (targetDesc.Format == srcDesc.Format && if (targetDesc.Format == srcDesc.Format &&
targetDesc.Width == srcDesc.Width && targetDesc.Width == srcDesc.Width &&
targetDesc.Height == srcDesc.Height) targetDesc.Height == srcDesc.Height)
{ {
return cachedTexture_; return cachedTexture;
} }
cachedTexture_ = nullptr;
} }
// for sharing this texture with unity device // for sharing this texture with unity device
srcDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED; srcDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
if (FAILED(device_->CreateTexture2D(&srcDesc, nullptr, &cachedTexture_))) if (FAILED(device_->CreateTexture2D(&srcDesc, nullptr, &cachedTexture)))
{ {
Debug::Error("IsolatedD3D11Device::GetCompatibleSharedTexture() => Creating shared texture failed."); Debug::Error("IsolatedD3D11Device::GetCompatibleSharedTexture() => Creating shared texture failed.");
return nullptr; return nullptr;
} }
return cachedTexture_; return cachedTexture;
} }
@@ -1,5 +1,6 @@
#pragma once #pragma once
#include <vector>
#include <d3d11.h> #include <d3d11.h>
#include <wrl/client.h> #include <wrl/client.h>
@@ -8,15 +9,16 @@
class IsolatedD3D11Device class IsolatedD3D11Device
{ {
public: public:
IsolatedD3D11Device(); explicit IsolatedD3D11Device(UINT cachedTextureNum);
~IsolatedD3D11Device(); ~IsolatedD3D11Device();
HRESULT Create(const Microsoft::WRL::ComPtr<IDXGIAdapter>& adapter); HRESULT Create(const Microsoft::WRL::ComPtr<IDXGIAdapter>& adapter);
Microsoft::WRL::ComPtr<ID3D11Device> GetDevice(); Microsoft::WRL::ComPtr<ID3D11Device> GetDevice();
Microsoft::WRL::ComPtr<ID3D11Texture2D> GetCompatibleSharedTexture( Microsoft::WRL::ComPtr<ID3D11Texture2D> GetCompatibleSharedTexture(
const Microsoft::WRL::ComPtr<ID3D11Texture2D>& src); const Microsoft::WRL::ComPtr<ID3D11Texture2D>& src,
UINT index);
private: private:
Microsoft::WRL::ComPtr<ID3D11Device> device_; Microsoft::WRL::ComPtr<ID3D11Device> device_;
Microsoft::WRL::ComPtr<ID3D11Texture2D> cachedTexture_; std::vector<Microsoft::WRL::ComPtr<ID3D11Texture2D>> cachedTextures_;
}; };
@@ -31,7 +31,8 @@ Duplicator::~Duplicator()
void Duplicator::InitializeDevice() void Duplicator::InitializeDevice()
{ {
device_ = std::make_shared<IsolatedD3D11Device>(); const UINT cachedTextureNum = 2;
device_ = std::make_shared<IsolatedD3D11Device>(cachedTextureNum);
if (FAILED(device_->Create(monitor_->GetAdapter()))) if (FAILED(device_->Create(monitor_->GetAdapter())))
{ {
@@ -210,6 +211,17 @@ const Duplicator::Frame& Duplicator::GetLastFrame() const
} }
void Duplicator::CopyLastTexture(
const Microsoft::WRL::ComPtr<ID3D11Device>& device,
const Microsoft::WRL::ComPtr<ID3D11Texture2D>& texture)
{
std::lock_guard<std::mutex> lock(mutex_);
ComPtr<ID3D11DeviceContext> context;
device->GetImmediateContext(&context);
context->CopyResource(texture.Get(), lastFrame_.texture.Get());
}
bool Duplicator::Duplicate() bool Duplicator::Duplicate()
{ {
if (!dupl_ || !device_) return false; if (!dupl_ || !device_) return false;
@@ -291,22 +303,23 @@ bool Duplicator::Duplicate()
return false; return false;
} }
auto copyTarget = device_->GetCompatibleSharedTexture(texture); auto sharedTexture = device_->GetCompatibleSharedTexture(texture, frame % 2);
if (!copyTarget) if (!sharedTexture)
{ {
return false; return false;
} }
ComPtr<ID3D11DeviceContext> context; ComPtr<ID3D11DeviceContext> context;
device_->GetDevice()->GetImmediateContext(&context); device_->GetDevice()->GetImmediateContext(&context);
context->CopyResource(copyTarget.Get(), texture.Get()); context->CopyResource(sharedTexture.Get(), texture.Get());
UpdateCursor(copyTarget, frameInfo); UpdateCursor(sharedTexture, frameInfo);
UpdateMetadata(frameInfo.TotalMetadataBufferSize); UpdateMetadata(frameInfo.TotalMetadataBufferSize);
{ {
std::lock_guard<std::mutex> lock(mutex_); std::lock_guard<std::mutex> lock(mutex_);
lastFrame_.texture = copyTarget; lastFrame_.frame = frame++;
lastFrame_.texture = sharedTexture;
lastFrame_.info = frameInfo; lastFrame_.info = frameInfo;
lastFrame_.metaData = metaData_; lastFrame_.metaData = metaData_;
} }
@@ -44,6 +44,7 @@ public:
struct Frame struct Frame
{ {
UINT frame = 0;
Microsoft::WRL::ComPtr<ID3D11Texture2D> texture; Microsoft::WRL::ComPtr<ID3D11Texture2D> texture;
DXGI_OUTDUPL_FRAME_INFO info; DXGI_OUTDUPL_FRAME_INFO info;
Metadata metaData; Metadata metaData;
@@ -60,6 +61,9 @@ public:
Microsoft::WRL::ComPtr<ID3D11Device> GetDevice(); Microsoft::WRL::ComPtr<ID3D11Device> GetDevice();
Microsoft::WRL::ComPtr<IDXGIOutputDuplication> GetDuplication(); Microsoft::WRL::ComPtr<IDXGIOutputDuplication> GetDuplication();
const Frame& GetLastFrame() const; const Frame& GetLastFrame() const;
void CopyLastTexture(
const Microsoft::WRL::ComPtr<ID3D11Device>& device,
const Microsoft::WRL::ComPtr<ID3D11Texture2D>& texture);
private: private:
void InitializeDevice(); void InitializeDevice();
@@ -81,6 +85,7 @@ private:
std::shared_ptr<class IsolatedD3D11Device> device_; std::shared_ptr<class IsolatedD3D11Device> device_;
Microsoft::WRL::ComPtr<IDXGIOutputDuplication> dupl_; Microsoft::WRL::ComPtr<IDXGIOutputDuplication> dupl_;
Frame lastFrame_; Frame lastFrame_;
UINT frame = 0;
volatile bool shouldRun_ = false; volatile bool shouldRun_ = false;
std::thread thread_; std::thread thread_;
@@ -71,8 +71,7 @@ void Monitor::Finalize()
void Monitor::Render() void Monitor::Render()
{ {
const auto& frame = duplicator_->GetLastFrame(); const auto& frame = duplicator_->GetLastFrame();
const auto texture = frame.texture; const auto& texture = frame.texture;
const auto frameInfo = frame.info; // clone
if (!texture) return; if (!texture) return;
@@ -97,9 +96,7 @@ void Monitor::Render()
} }
else else
{ {
ComPtr<ID3D11DeviceContext> context; duplicator_->CopyLastTexture(GetDevice(), unityTexture_);
GetDevice()->GetImmediateContext(&context);
context->CopyResource(unityTexture_, texture.Get());
} }
} }