我在使用内存中的网络摄像头帧缓冲区中的图像数据更新DirectX 11纹理时遇到了困难。我设法从缓冲区中的单个帧创建了一个纹理,但由于缓冲区被下一帧覆盖,纹理没有更新。因此,我只剩下一张快照图像,而不是我所追求的实时流。
我正在尝试使用Map/Unmap方法来更新ID 3D 11 Texture 2D资源,因为这应该比使用UpdateSubresource方法更有效。我还没有设法让这两种方法都起作用。我是DirectX的新手,我只是找不到关于如何完成此操作的好解释。
在此处创建纹理:
bool CreateCamTexture(ID3D11ShaderResourceView** out_srv, RGBQUAD* ptrimg, int* image_width, int* image_height)
{
ZeroMemory(&desc, sizeof(desc));
desc.Width = *image_width;
desc.Height = *image_height;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
std::cout << ptrimg << std::endl;
subResource.pSysMem = ptrimg;
subResource.SysMemPitch = desc.Width * 4;
subResource.SysMemSlicePitch = 0;
g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
ZeroMemory(&srvDesc, sizeof(srvDesc));
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = desc.MipLevels;
srvDesc.Texture2D.MostDetailedMip = 0;
g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, out_srv);
if (pTexture != NULL) {
pTexture->Release();
}
else
{
std::cout << "pTexture is NULL ShaderResourceView not created" << std::endl;
}
return true;
}
bool CreateDeviceD3D(HWND hWnd)
{
// Setup swap chain
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = 2;
sd.BufferDesc.Width = 0;
sd.BufferDesc.Height = 0;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = hWnd;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.Windowed = TRUE;
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
UINT createDeviceFlags = 0;
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
D3D_FEATURE_LEVEL featureLevel;
const D3D_FEATURE_LEVEL featureLevelArray[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, };
尝试Map/取消Map纹理:
void UpdateCamTexture() {
D3D11_MAPPED_SUBRESOURCE mappedResource;
ZeroMemory(&mappedResource, sizeof(D3D11_MAPPED_SUBRESOURCE));
g_pd3dDeviceContext->Map(
pTexture,
0, //0,
D3D11_MAP_WRITE_DISCARD,
0,
&mappedResource);
memcpy(mappedResource.pData, listener_instance.pImgData, sizeof(listener_instance.pImgData));
// Reenable GPU access to the vertex buffer data.
g_pd3dDeviceContext->Unmap(pTexture, 0);
std::cout << "texture updated" << std::endl;
}
我没有得到一个错误,图像只是黑色。我没有调试层启用虽然。
1条答案
按热度按时间v09wglhw1#
在指针
listener_instance.pImgData
上调用sizeof
并不是你想要的,因为它返回的是指针类型的大小(在x64架构上是8),而不是指针所指向的数组的大小。用图像数据的大小(以字节为单位)调用memcpy
也不是完全正确的解决方案。更多细节请参见here。我将从那里复制答案,以防它被删除。马克西姆斯·米尼穆斯的回答是:
检查从贴图调用返回的间距-您假设它是
width * 4
(对于32位RGBA),但它可能不是(特别是如果您的纹理不是2的幂或它的宽度不是4的倍数)。如果间距等于宽度 * 格式中的字节数,则一次只能对整个块执行
memcpy
操作。否则,必须一次对一行执行memcpy
操作。示例代码,请原谅C-isms:
假定src和dst是32位RGBA数据
宽度和高度来自
ID3D11Texture2D::GetDesc
当然,你也可以包括一个测试,如果
(msr.RowPitch == width * 4)
为真,那么就对整个过程做一个memcpy
测试。