Я разрабатываю приложение для виртуальной реальности в Unity, которое использует собственный плагин для декодирования видео, и я хотел выполнить некоторую обработку декодированного видеокадра.
Первым моим шагом было использование вычислительного шейдера Unity, которыйбыл отправлен из скрипта C # в приложении Unity.Это сработало, и я увидел ожидаемые результаты, но у меня была проблема синхронизации с извлечением параметра из собственного плагина, работающего в потоке рендеринга, который необходимо было передать в вычислительный шейдер, работающий в основном потоке.
Я думал, что это можно решить путем преобразования вычислительного шейдера Unity в вычислительный шейдер D3D11 и обработки декодированного кадра в собственном плагине, как только он выскочит из декодера.Это также дало мне ожидаемые результаты, но с огромными затратами на производительность.Приложение удаляет кадры, и при использовании RenderDoc для профилирования одного кадра я вижу около 32 мс для вызова диспетчеризации вычислений в плагине по сравнению с 3 мс при использовании вычислительного шейдера Unity.
Я не могу найти никакой информации о том, почемуесть такое расхождение между тогда двумя.Я попытался упростить шейдер D3D11 до простой записи нулей, а профилировщик все еще показывает около 32 мс, что заставляет меня думать, что это связано с моей настройкой шейдера в плагине.
Я включил некоторый кодчтобы показать мою настройку и выполнение вычислительного шейдера плагина.
Вычислить шейдер в родном плагине C ++:
void process()
{
ID3D11DeviceContext* ctx = NULL;
device->GetImmediateContext(&ctx);
ctx->UpdateSubresource(_pCB, 0, nullptr, &_bufferStruct, 0, 0);
if (!_resourcesSet) {
// Set read texture
ID3D11ShaderResourceView * inY = nullptr;
ID3D11ShaderResourceView * inU = nullptr;
ID3D11ShaderResourceView * inV = nullptr;
_inputTexture->getSRVs(&inY, &inU, &inV);
// Set write texture
ID3D11UnorderedAccessView * outY;
ID3D11UnorderedAccessView * outU;
ID3D11UnorderedAccessView * outV;
_outputTexture->getUAVs(&outY, &outU, &outV);
ctx->CSSetConstantBuffers(0, 1, &_pCB);
ctx->CSSetShaderResources(0, 1, &inY);
ctx->CSSetShaderResources(1, 1, &inU);
ctx->CSSetShaderResources(2, 1, &inV);
ctx->CSSetUnorderedAccessViews(0, 1, &outY, nullptr);
ctx->CSSetUnorderedAccessViews(1, 1, &outU, nullptr);
ctx->CSSetUnorderedAccessViews(2, 1, &outV, nullptr);
ctx->CSSetShader(_computeShader, NULL, 0);
_resourcesSet = true;
}
ctx->Dispatch(outputWidth / 8, outputHeight / 8, 1);
ctx->Release();
}
Сам упрощенный вычислительный шейдер:
SamplerState TextureSampler
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = Wrap;
AddressV = Wrap;
};
Texture2D<float> inY : register(t0);
Texture2D<float> inU : register(t1);
Texture2D<float> inV : register(t2);
RWTexture2D<float> outY : register(u0);
RWTexture2D<float> outU : register(u1);
RWTexture2D<float> outV : register(u2);
[numthreads(8,8,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
float3 col = float3(0.0, 0.0, 0.0);
outY[id.xy] = col.r;
outU[id.xy / 2] = col.g;
outV[id.xy / 2] = col.b;
}
Isесть что-то очевидное, чего мне не хватает, или единство просто очень хорошо в оптимизации?