как сделать блокировку ожидания для вычислительного шейдера с Direct3D11? - PullRequest
1 голос
/ 05 марта 2019

У меня есть конвейер постобработки, который использует вычислительный шейдер для обработки текстуры и записи ее в RWByteAddressBuffer.

Затем содержимое RWByteAddressBuffer отправляется на устройство FPGA через прямой доступ к памяти (AMD DirectGMAтехнология).Это означает, что я инициирую внешнее устройство для доступа к физическим байтам этого буфера без API Direct3D, зная об этом.

Вот суть кода:

_context->CSSetShaderResources(0,1,_nonMsaaSrv.GetAddressOf());
_context->CSSetUnorderedAccessViews(0, 1, _unorderedAccessView.GetAddressOf(),nullptr);
_context->CSSetShader(_converter.Get(),0,0);
_context->Dispatch(1920, 1200, 1);

// ... wait for direct3d compute shader to finish processing?
// send the bytes to the fpga:
_dmaController->StartDMA(_d3dBufferPhysicalAddress, fpgaLogicalAddress);

Все работает, ноПроблема в том, что я не смог найти способ заблокировать поток или получить событие, которое указывает, что вычислительный шейдер завершил свою работу на графическом процессоре.

Этот вопрос предлагает решение, использующее ID3D11Query длясделать какой-то опрос.но я понимаю, что это просто занятое ожидание .Я надеялся найти лучшее решение, которое могло бы позволить потоку блокироваться, ожидая какого-то события.С такими API, как Cuda / OpenCL, это довольно тривиально.

Так можно ли сделать ожидание блокировки для вычислительного шейдера в direct3D 11?если так как?

Ответы [ 2 ]

2 голосов
/ 07 марта 2019

Если нет необходимости поддерживать Windows 7/8, это можно сделать с помощью обновленных интерфейсов ID3D11Device5, ID3D11DeviceContext4 & ID3D11Fence, которые доступны в Windows 10 v1703 и более поздних версиях.

Создание объекта забора:

HR(_d3dDevice->CreateFence(0, D3D11_FENCE_FLAG_NONE, __uuidof(ID3D11Fence), reinterpret_cast<void**>(_syncFence.GetAddressOf())));

В цикле обработки мы отправляем вычислительный шейдер и сразу после него ставим в очередь сигнал с увеличенным счетчиком:

++_syncCounter;
_context->Dispatch(1920, 1200, 1);
HR(_context->Signal(_syncFence.Get(), _syncCounter));
HR(_syncFence->SetEventOnCompletion(_syncCounter,_syncEvent.get()));  

// ожидание события (может быть в другом потоке)

_syncEvent.wait(); // WaitForSingleObject

Примеры (хотя для Direct3D12) можно найти здесь .

0 голосов
/ 07 марта 2019

ID3D11Query - это механизм, который вы ищете;В Direct3D 11 нет ничего основанного на событиях. Это механизм опроса, но он не такой, как обычное ожидание занятости на процессоре.

Вы всегда можете профилировать его, чтобы посмотреть, какую нагрузку он добавляет, особенно если вы добавляетезадержка проверки query->GetData через различные интервалы (10 мс, 100 мс и т. д.), чтобы увидеть, улучшается ли ваша производительность.

...