什么因素决定了DXGI_FORMAT?

What factors determine DXGI_FORMAT?

我对directx不熟悉,但是我运行在一个小项目中遇到了一个问题,其中一部分涉及捕获directx数据。我希望,下面我说得有道理。

一般问题:

我想知道什么因素决定了后缓冲区中纹理的 DXGI_FORMAT(硬件?,OS?,应用程序?,directx 版本?)。更重要的是,当从后台缓冲区捕获纹理时,是否可以通过提供格式作为参数来接收所需格式的纹理,并在必要时自动转换格式。

关于我的问题的细节:

我使用 Open Broadcaster Software (OBS) 从游戏中捕获屏幕,并在流式传输之前使用特定库 (OpenCV) 处理它们。我注意到,在更新 Windows 和 OBS 之后,我得到 'DXGI_FORMAT_R10G10B10A2_UNORM' 作为 DXGI_FORMAT。这对我来说是个问题,因为据我所知,当颜色为 10 位时,OpenCV 不提供构建 OpenCV 对象的便捷方法。以下是修改后的 OBS 源文件中的一些相关行。

d3d11_copy_texture(data.texture, backbuffer);
...
hlog(toStr(data.format));  // prints 24 = DXGI_FORMAT_R10G10B10A2_UNORM
...
ID3D11Texture2D* tex;
bool success = create_d3d11_stage_surface(&tex);
if (success) {
    ...
    HRESULT hr = data.context->Map(tex, subresource, D3D11_MAP_READ, 0, &mappedTex);
    ...
    Mat frame(data.cy, data.cx, CV_8UC4, mappedTex.pData, (int)mappedTex.RowPitch); //This creates an OpenCV Mat object.
                                               //No support for 10-bit coors. Expects 8-bit colors (CV_8UC4 argument).
                                               //When the resulting Mat is viewed, colours are jumbled (Probably because 10-bits did not fit into 8-bits).

在更新之前(一年前我在做这个),我可能收到 DXGI_FORMAT = DXGI_FORMAT_B8G8R8A8_UNORM,因为上面的代码曾经有效。

现在我想知道发生了什么变化,我是否可以修改OBS的源代码以接收所需的数据DXGI_FORMAT。

上面调用的

'create_d3d11_stage_surface' 方法设置了 DXGI_FORMAT,但我不确定它是指 'give me data with this DXGI_FORMAT' 还是 'I know you work with this format, give me what you have'.

static bool create_d3d11_stage_surface(ID3D11Texture2D **tex)
{
    HRESULT hr;

    D3D11_TEXTURE2D_DESC desc      = {};
    desc.Width                     = data.cx;
    desc.Height                    = data.cy;
    desc.Format = data.format;
    ...

我希望,用 DXGI_FORMAT_B8G8R8A8_UNORM 覆盖 desc.Format 会导致该格式在上面的 ID3D11DeviceContext::Map 调用中作为参数传递,并且我会得到指定格式的数据.但这没有用。

渲染目标的选择取决于应用程序,但他们需要根据 Direct3D 硬件功能级别选择一个。交换链中渲染目标的格式通常是显示扫描输出格式:

DXGI_FORMAT_R8G8B8A8_UNORM
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
DXGI_FORMAT_B8G8R8A8_UNORM
DXGI_FORMAT_B8G8R8A8_UNORM
DXGI_FORMAT_R10G10B10A2_UNORM
DXGI_FORMAT_R16G16B16A16_FLOAT
DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM (rare)

请参阅 DXGI documentation 了解按功能级别划分的受支持格式和用法的完整列表。

Direct3D 11 在您复制资源(例如复制到暂存渲染纹理)时不会进行格式转换,因此如果您想进行格式转换,您需要自己处理。请注意,可以在 DirectXTex.

中找到所有 DXGI 格式的 CPU 端转换代码

决定格式的是应用程序。最简单的是 R8G8B8A8,它只表示 RGB 和 alpha 值。但是,如果开发人员决定他将使用 HDR,则后备缓冲区可能是 R11B11G10,因为您可以在那里存储更精确的数据,而无需 alpha 通道信息。例如,如果游戏是黑白的,则无需将所有 RGB 通道都保留在后台缓冲区中,您可以使用更简单的格式。希望对您有所帮助。