【问题标题】:What factors determine DXGI_FORMAT?哪些因素决定了 DXGI_FORMAT?
【发布时间】:2017-08-23 22:41:57
【问题描述】:

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

一般问题:

我想知道是什么因素决定了后缓冲区中纹理的 DXGI_FORMAT(硬件?操作系统?应用程序?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,但我不确定它是否意味着'给我这个DXGI_FORMAT的数据'或'我知道你使用这种格式,给我你有什么'。

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 调用中作为参数传递,并且我会得到具有指定格式的数据。但这不起作用。

【问题讨论】:

  • 纹理的DXGI_FORMAT在纹理创建期间指定。您可能需要将 r10g10b10a2 数据“转换”为 b8r8g8a8 到 CPU 中,然后将其提供给 OpenCV 进行处理。
  • 我检查了 directxtex,但我认为在我的情况下,从 OBS 中的另一个地方获取图像会更容易。

标签: directx directx-11


【解决方案1】:

渲染目标的选择取决于应用程序,但他们需要根据 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 不会在您复制资源(例如复制到暂存渲染纹理)时进行格式转换,因此如果您想要进行格式转换,您需要自己处理。请注意,所有 DXGI 格式的 CPU 端转换代码都可以在 DirectXTex 中找到。

【讨论】:

  • 所以在我的情况下是游戏设置格式(基于硬件功能级别)。
  • @Chuck 我们的纹理呢?我们是否必须为渲染目标的 dxgi_format 考虑纹理的 dxgi_format,还是不相关?谢谢。
  • 它们通常是独立的,除了您希望如何处理色彩空间。见This GPU Gems 3 article
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 2022-10-01
    • 2017-07-31
    • 2018-08-28
    • 1970-01-01
    • 2021-03-29
    • 2015-04-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多