具有共享资源的 D3DX11SaveTextureToFile

发布于 2024-10-30 18:04:10 字数 1674 浏览 2 评论 0原文

我使用共享资源将纹理从一个 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);

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

I'm using shared resources to send textures from one D3D11 device to another, so that I can copy the back buffer over the second device and use the second device context to save that texture to a file. This seems to be working, but when I save the texture, it saves an empty PNG.
I tried saving the texture with the primary device context and it works, except if I use the D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX MiscFlag, which I need in order to share the resources.
Is there any reason D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX prevents a texture from being saved ? Or am I maybe missing something out in order for it to work ?

Here is the code I'm using:

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));

And this is the code used to save the shared textue in the second device

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);

Also, the code that is supposed to save the shared texture to the filesystem is running in it's own thread.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

枫以 2024-11-06 18:04:11

这是我解决问题的方法。事实证明,使用 D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX 杂项标志不允许将纹理保存到文件中。因此,我使用 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 函数中,它由辅助上下文处理。
顺便说一句,我还没有对它进行很多测试,我今天早上只是将它组合在一起,在某些情况下它可能不起作用,但它解决了我使用另一个标志时遇到的问题,这导致保存空图像归档。

Here is how I solved the problem. Turns out, using the D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX misc flag doesn't allow to save the texture to a file. So I used the D3D11_RESOURCE_MISC_SHARED flag instead with a regular mutex, without using the DXGIKeyedMutex stuff.

Copy the back buffer to shared texture and create a shared handle:

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();

Now that we have a shared copy of the back buffer and handle to it, we can save it to a file from another thread without hogging the device context:

// 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();
    }
}

Basically this allows me to save HD screen captures without killing the frame rate because my device context is not stuck in the D3DX11SaveTextureToFile function, it's handled by the secondary context.
On a side note, I've not tested it a whole lot, I just hack this together this morning, it might not work in some cases, but it solves the problem I had with the other flag, which caused empty images to be saved to file.

独行侠 2024-11-06 18:04:11

从拥有 backBuffer 的 _device 中创建 CreateTexture2D 和 CopyResource 不是更符合逻辑吗?

Wouldn't it be more logical to CreateTexture2D and CopyResource from the _device that owns backBuffer?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文