Первый раз пытаюсь что-то отрендерить и у меня большие проблемы... Я использую библиотеку DirectN и класс SwapChainSurface из KlearTouch.MediaPlayer. Я пытаюсь визуализировать кадр BGRA32 с помощью D3D11Device.
Для этого я немного изменил OnNewSurfaceAvailable:
public void OnNewSurfaceAvailable2(Action<ID3D11Device, ID3D11DeviceContext> updateSurface)
{
if (rendering)
{
return;
}
try
{
if (this.swapChain is null || swapChainComObject is null)
{
return;
}
swapChainComObject.GetDesc(out var swapChainDesc).ThrowOnError();
if (swapChainDesc.BufferDesc.Width != PanelWidth || swapChainDesc.BufferDesc.Height != PanelHeight)
{
swapChainComObject.ResizeBuffers(2, PanelWidth, PanelHeight, DXGI_FORMAT.DXGI_FORMAT_UNKNOWN, 0).ThrowOnError();
}
var device = swapChain.Object.GetDevice1().Object.As<ID3D11Device>();
device.GetImmediateContext(out var context);
// context.ClearRenderTargetView(renderTargetView.Object, new []{0f, 1f, 1f, 1f});
updateSurface(device, context);
swapChainComObject.Present(1, 0).ThrowOnError();
}
catch (ObjectDisposedException)
{
Reinitialize();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("\nException: " + ex, nameof(SwapChainSurface) + '.' + nameof(OnNewSurfaceAvailable));
}
rendering = false;
}
OnSurfaceAvailable2 вызывается из:
void VideoFrameArrived(Bgra32VideoFrame frame)
{
DispatcherQueue.TryEnqueue(() =>
{
previewSurface.OnNewSurfaceAvailable2((device, context) =>
{
var size = frame.m_height * frame.m_height * 4;
D3D11_TEXTURE2D_DESC td;
td.ArraySize = 1;
td.BindFlags = (uint) D3D11_BIND_FLAG.D3D11_BIND_SHADER_RESOURCE;
td.Usage = D3D11_USAGE.D3D11_USAGE_DYNAMIC;
td.CPUAccessFlags = (uint) D3D11_CPU_ACCESS_FLAG.D3D11_CPU_ACCESS_WRITE;
td.Format = DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM;
td.Height = (uint) frame.m_height;
td.Width = (uint) frame.m_width;
td.MipLevels = 1;
td.MiscFlags = 0;
td.SampleDesc.Count = 1;
td.SampleDesc.Quality = 0;
D3D11_SUBRESOURCE_DATA srd;
srd.pSysMem = frame.m_pixelBuffer;
srd.SysMemPitch = (uint) frame.m_height;
srd.SysMemSlicePitch = 0;
var texture = device.CreateTexture2D<ID3D11Texture2D>(td, new []{srd});
var mappedResource = context.Map(texture.Object, 0, D3D11_MAP.D3D11_MAP_WRITE_DISCARD);
var mappedData = mappedResource.pData;
unsafe
{
Buffer.MemoryCopy(frame.m_pixelBuffer.ToPointer(), mappedData.ToPointer(), size, size);
}
// Just for debug
var pixelsInFrame = new byte[size];
var pixelsInResource = new byte[size];
Marshal.Copy(frame.m_pixelBuffer, pixelsInFrame, 0, size);
Marshal.Copy(mappedResource.pData, pixelsInResource, 0, size);
context.Unmap(texture.Object, 0);
});
});
}
Проблема в том, что я не вижу ничего визуализированного, а поверхность остается черной, и я предполагаю, что этого не должно быть.
Я решил свою проблему. У меня было слишком мало знаний о DX11, поэтому мне пришлось больше изучать, как там все работает. Обладая этими знаниями, я обновил репозиторий, который может отображать предварительный просмотр с карты дизайна черной магии. Это всего лишь пример со многими проблемами, поэтому будьте осторожны и не стесняйтесь искать там вдохновение.
Остальной код для DirectX 11 реализован точно так же, как и в KlearTouch.MediaPlayer. Приложение использует карту захвата BlackMagic и камеру. Я выложу весь проект на github и обновлю ответ.
Я создал общедоступный репозиторий со всем проектом и обновил вопрос.
Этот проект представляет собой целый проект, который не компилируется и не требует сторонних разработчиков. Вы должны опубликовать более простую вещь stackoverflow.com/help/минимально-воспроизводимый-пример
Какую проблему производит buld? Я могу попытаться избавиться от ссылки на DeckLinkAPI, если это проблема, и других ненужных вещей.
Это как минимум одна проблема. Минимальный пример — это тот, который работает везде.
Извините, что не ответил. Я уже решил свою проблему. Я обновил вопрос и репозиторий своим решением.





Здесь разное количество вопросов.
Первый кадр прибыл, у вас есть
var texture = device.CreateTexture2D<ID3D11Texture2D>(td, new []{srd});
Таким образом, вы создаете текстуру, но нигде ее не используете, ее нужно перенести в цепочку обмена (можно сделать CopyResource в контексте устройства или нарисовать полноэкранный треугольник/квадроцикл).
Обратите внимание, что CopyResource будет работать только в том случае, если ваша цепочка обмена имеет тот же размер, что и ваша входящая текстура, что довольно маловероятно, поэтому вам, скорее всего, придется рисовать блит с шейдером.
Также вы дважды копируете данные в текстуре:
var texture = device.CreateTexture2D<ID3D11Texture2D>(td, new []{srd});
Поскольку вы предоставляете исходные данные, контент уже есть.
также неправильный шаг: srd.SysMemPitch = (uint)frame.m_height;
шаг - это длина (в байтах) строки, поэтому она должна быть:
srd.SysMemPitch = frame.GetRowBytes();
Также обратите внимание, что в случае непеределанной рамы Decklink, GetRowBytes может отличаться от width*4 (они могут выравнивать размер строки до кратного 16/32 или других значений).
Далее, в случае карты ресурсов неверно также следующее:
unsafe
{
Buffer.MemoryCopy(frame.m_pixelBuffer.ToPointer(), mappedData.ToPointer(), size, size);
}
Вы не проверяете требования к шагу/шагу текстуры (которые также могут быть разными),
поэтому вам нужно сделать:
if (mappedResource.RowPitch == frame.GetRowBytes())
{
//here you can use a direct copy as above
}
else
{
//here you need to copy data line per line
}
Большое тебе спасибо. Ваш ответ совсем не помог мне, когда я впервые увидел его, потому что я слишком мало знал о DirectX 11 и рендеринге. Мне пришлось сделать большой шаг назад и сначала читать руководства, смотреть видео и пробовать простые вещи. Теперь это имеет гораздо больше смысла. Особенно первая и последняя часть намного понятнее и мне очень помогли. Спасибо.
Благодаря вашим советам я смог исправить свой код. Спасибо
У вас есть готовый проект по воспроизведению?