第一次试着做些什么而我有大麻烦..。我正在使用DirectN库和KlearTouch.MediaPlayer中的SwapChainSurface类。我正在尝试使用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);
});
});
}问题是,我看不到任何渲染和表面保持黑色,我认为它不应该。
更新:项目储存库
更新2:
我解决了我的问题。我对DX11知之甚少,所以我不得不研究更多的东西是如何在那里工作的。有了这些知识,我更新了存储库,它可以显示来自黑色魔法设计卡的预览。它只是许多问题的例子,所以要小心,在那里自由地寻找或激发灵感。
发布于 2022-05-06 14:00:02
这里有各种各样的问题。
第一帧到了,你有
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可能与宽度*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
}https://stackoverflow.com/questions/72127664
复制相似问题