简体   繁体   中英

Data race in passing a texture across threads in DirectX

I'm experiencing a data race in a DirectX application with two threads: a consumer and a producer.

The first thread ( producer ) is a screen grabber which uses desktop duplication to get a desktop image in a texture. It creates a ID3D11Device and ID3D11DeviceContext on adapter X.

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

The second thread (consumer) a ID3D11Device and ID3D11DeviceContext on the same adapter X

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

Unfortunately I'm having random problems with this approach (invalid textures or pointers causing other DX libraries expecting a valid texture to fail) which disappear if I for example put a sleep(1000) in the producer thread. This makes me thing it could be a data race thing.

Is there any need of synchronization across the two threads? I'm deliberately skipping texture Release() for now (even though I might run out of GPU memory eventually) to debug this data race.

  • Your code releases pointer desktop_texture->Release(); and then for some reason return it, this looks like a typo and it probably supposed to be return encapsulate(return_texture);
  • To process texture using different device you will need to create resource with D3D11_RESOURCE_MISC_SHARED flag, convert it to HANDLE by calling IDXGIResource::GetSharedHandle and then make usable by calling ID3D11Device::OpenSharedResource .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM