D3DX11SaveTextureToFile具有共享资源

时间:2011-04-07 17:21:54

标签: c++ multithreading directx

我正在使用共享资源将纹理从一个D3D11设备发送到另一个设备,这样我就可以在第二个设备上复制后端缓冲区,并使用第二个设备上下文将该纹理保存到文件中。这似乎有效,但是当我保存纹理时,它会保存一个空的PNG。 我尝试使用主设备上下文保存纹理并且它可以工作,除非我使用D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX MiscFlag,我需要它来共享资源。 是否有任何原因D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX阻止纹理被保存?或者我可能会遗漏一些东西以使其起作用?

以下是我正在使用的代码:

D3D11_TEXTURE2D_DESC td;
backBuffer->GetDesc(&td);
td.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
this->_device->CreateTexture2D(&td, 0, &g_tex);
this->_context->CopyResource(g_tex, backBuffer);

// saves a blank image if using D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX
D3DX11SaveTextureToFile(this->_context, g_tex, D3DX11_IFF_JPG, "test.jpg");

g_tex->QueryInterface(__uuidof(IDXGIResource), reinterpret_cast<void **>(&g_dxgiResource));
g_dxgiResource->GetSharedHandle(&g_shaderHandle);
g_dxgiResource->Release();
g_tex->QueryInterface(__uuidof(IDXGIKeyedMutex), reinterpret_cast<void **>(&g_dxgiMutex));

这是用于在第二个设备中保存共享文本​​的代码

ID3D11Texture2D *texture = 0;
IDXGIKeyedMutex *keyedMutex = 0;
device2->OpenSharedResource(g_shaderHandle, __uuidof(ID3D11Texture2D), reinterpret_cast<void **>(&texture));
texture->QueryInterface(__uuidof(IDXGIKeyedMutex), reinterpret_cast<void **>(&keyedMutex));
UINT acqKey = 0;
UINT relKey = 1;
DWORD timeout = 16;
DWORD res = keyedMutex->AcquireSync(acqKey, timeout);
if (res == WAIT_OBJECT_0 && texture)
{
    // saves a blank image too
    D3DX10SaveTextureToFile(texture, D3DX10_IFF_JPG, "test2.jpg");
}
keyedMutex->ReleaseSync(relKey);

此外,应该将共享纹理保存到文件系统的代码正在其自己的线程中运行。

2 个答案:

答案 0 :(得分:4)

以下是我解决问题的方法。事实证明,使用D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX misc标志不允许将纹理保存到文件中。所以我使用D3D11_RESOURCE_MISC_SHARED标志代替普通的互斥锁,而不使用DXGIKeyedMutex。

将后台缓冲区复制到共享纹理并创建共享句柄:

D3D11_TEXTURE2D_DESC td;
backBuffer->GetDesc(&td);
td.MiscFlags = D3D11_RESOURCE_MISC_SHARED;

this->_device->CreateTexture2D(&td, 0, &g_tex);
this->_context->CopyResource(g_tex, backBuffer);
IDXGIResource *dxgiResource = 0;
g_tex->QueryInterface(__uuidof(IDXGIResource), reinterpret_cast<void **>(&dxgiResource));
dxgiResource->GetSharedHandle(&g_shaderHandle);
dxgiResource->Release();
backBuffer->Release();

现在我们有一个后台缓冲区的共享副本和句柄,我们可以将它保存到另一个线程的文件中,而不会占用设备上下文:

// device_2 and context_2 are the "secondary" device and context
bool imgSaved = true;
ID3D11Texture2D *texture = 0;
HRESULT h = WaitForSingleObject(g_mutex, INFINITE);
if (h == WAIT_OBJECT_0)
{
    // check to see if there is an image to save
    if (wdata->hasFrame)
    {
        wdata->hasFrame = false;
        imgSaved = false
    }
}
ReleaseMutex(g_mutex);
if (!imgSaved)
{
    device_2->OpenSharedResource(g_shaderHandle, __uuidof(ID3D11Texture2D), (LPVOID*)&texture);
    if (texture)
    {
        h = D3DX11SaveTextureToFile(context_2, texture, D3DX11_IFF_PNG, "image.png");
        texture->Release();
    }
}

基本上这允许我保存高清屏幕捕获而不会破坏帧速率,因为我的设备上下文没有卡在D3DX11SaveTextureToFile函数中,它由辅助上下文处理。 在旁注中,我没有对它进行过多次测试,我今天早上一起破解它,在某些情况下它可能不起作用,但它解决了我对另一个标志的问题,导致空图像被保存提交。

答案 1 :(得分:0)

拥有backBuffer的_device中的CreateTexture2D和CopyResource不合逻辑吗?