c ++ - Data race i forbipasserende tekstur på tværs af tråde i DirectX

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg oplever et datacross i en DirectX-applikation med to tråde: en forbruger og en producent.


Den første tråd ( producent ) er en skærmgrabber, der bruger desktopduplikation til at få et desktopbillede i en tekstur. Den opretter en ID3D11Device og ID3D11DeviceContext på adapter X. [11]


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


Den anden tråd (forbruger) en ID3D11Device og ID3D11DeviceContext på den samme 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


Desværre har jeg tilfældige problemer med denne fremgangsmåde (ugyldige teksturer eller pointers, der forårsager andre DX-biblioteker, der forventer en gyldig tekstur til at mislykkes), som forsvinder, hvis jeg f.eks. Sætter en sleep(1000) i producentens tråd. være en data race ting.


Er der behov for synkronisering på tværs af de to tråde? Jeg overvejer med tiden overskridelse af tekstur Release() for nu (selvom jeg måske løber tør for GPU-hukommelse til sidst) for at debugge denne datacance.

Bedste reference



  • Din kode frigiver pegeren desktop\_texture->Release(); og derefter af en eller anden grund returnerer den. Det ligner en skrivefelt, og det skal sandsynligvis være return encapsulate(return\_texture);

  • Hvis du vil behandle tekstur ved hjælp af anden enhed, skal du oprette ressource med D3D11\_RESOURCE\_MISC\_SHARED flag, konvertere den til HANDLE ved at ringe IDXGIResource::GetSharedHandle og derefter gøre brugbar af ringer ID3D11Device::OpenSharedResource.