c++ - 在 DirectX 中跨线程传递纹理的数据竞争

标签 c++ windows multithreading directx directx-11

我在具有两个线程的 DirectX 应用程序中遇到数据竞争:一个消费者和一个生产者。

第一个线程 (producer) 是一个屏幕抓取器,它使用 desktop duplication获取纹理中的桌面图像。它在适配器 X 上创建 ID3D11Device 和 ID3D11DeviceContext。

dxgi_dd->AcquireNextFrame(INFINITE, &frame_info, &desktop_resource);

ID3D11Texture2D *desktop_texture;
desktop_resource->QueryInterface(__uuidof(ID3D11Texture2D), (void **)&desktop_texture);
desktop_resource->Release();

D3D11_TEXTURE2D_DESC texture_desc;

memset(&texture_desc, 0, sizeof(texture_desc));
texture_desc.Width = desktop_desc.Width;
texture_desc.Height = desktop_desc.Height;
texture_desc.MipLevels = 1;
texture_desc.ArraySize = 1;
texture_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
texture_desc.SampleDesc.Count = 1;
texture_desc.SampleDesc.Quality = 0;
texture_desc.Usage = D3D11_USAGE_DEFAULT;
texture_desc.BindFlags = 0;
texture_desc.CPUAccessFlags = 0;
texture_desc.MiscFlags = 0;

d3d11_device->CreateTexture2D(&texture_desc, NULL, &return_texture);

// Copy it to a return texture
immediate_context->CopyResource(return_texture, desktop_texture);
immediate_context->Flush();

dxgi_dd->ReleaseFrame();
desktop_texture->Release();

return encapsulate(return_texture); // Thread returns the pointer encapsulated in a structure

同一适配器 X 上的第二个线程(消费者)一个 ID3D11Device 和 ID3D11DeviceContext

ID3D11Texture2D *dx_input_texture;
D3D11_TEXTURE2D_DESC desc;
ZeroMemory(&desc, sizeof(D3D11_TEXTURE2D_DESC));
desc.Width = received_texture.width;
desc.Height = received_texture.height;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_RENDER_TARGET;
desc.CPUAccessFlags = 0;
d3d11_device->CreateTexture2D(&desc, NULL, &dx_input_texture)

ID3D11Texture2D *frame_texture = (ID3D11Texture2D*)received_texture.pointer_received_from_other_thread;

immediate_context->CopyResource(dx_input_texture, frame_texture);
immediate_context->Flush();

// Use dx_input_texture now

不幸的是,我在使用这种方法时遇到了随机问题(无效的纹理或指针导致其他 DX 库期望有效纹理失败),如果我将 sleep(1000) 放入生产者线程。这让我觉得这可能是一场数据竞赛。

两个线程之间是否需要同步?我现在故意跳过纹理 Release()(即使我最终可能会耗尽 GPU 内存)以调试此数据竞争。

最佳答案

  • 您的代码释放指针 desktop_texture->Release(); 然后由于某种原因返回它,这看起来像一个拼写错误,它可能应该是 return encapsulate(return_texture);
  • 要使用不同 设备处理纹理,您需要使用D3D11_RESOURCE_MISC_SHARED 标志创建资源,通过调用IDXGIResource 将其转换为HANDLE::GetSharedHandle,然后通过调用 ID3D11Device::OpenSharedResource 使其可用。

关于c++ - 在 DirectX 中跨线程传递纹理的数据竞争,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50365387/

相关文章:

c++ - SDL2 + ffmpeg2 间歇性点击而不是音频

c++ - 在多线程程序中正确使用 QSqlDatabase

c++ - 从设备实例路径字符串中获取设备实例 DWORD

windows - 如何创建名称大小写不同的目录? (区分大小写的 CreateDirectory 函数)

python - 如何使用 msilib 从 python 模块创建 .msi 文件的示例

.net - .net中实现多线程的不同方式是什么?

Linux 中的 Java 进程需要初始预热

c++ - 关于使用 C++ istream_iterator 从文件中读取部分数据的一些事情

c++ - 删除动态数组的一部分并增加其他部分

c# - 为 DI 容器创建线程安全的单例包装器