You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建与渲染目标匹配的ID3D11Texture2D暂存纹理?

问题描述

我通过以下代码创建了DirectX 11交换链及相关资源:

DXGI_SWAP_CHAIN_DESC swapchainDesc;

// Clear out the struct for use
ZeroMemory(&swapchainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));

// Fill the swap chain description struct
swapchainDesc.BufferCount = 1;                                    // one back buffer
swapchainDesc.BufferDesc.Width = width;
swapchainDesc.BufferDesc.Height = height;
swapchainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;     // use 32-bit color
swapchainDesc.BufferDesc.RefreshRate.Numerator = 60;
swapchainDesc.BufferDesc.RefreshRate.Denominator = 1;
swapchainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;      // how swap chain is to be used
swapchainDesc.OutputWindow = hWnd;                                // the window to be used
swapchainDesc.SampleDesc.Count = 1;                               // how many multisamples
swapchainDesc.SampleDesc.Quality = 0;                             // multisample quality level
swapchainDesc.Windowed = TRUE;                                    // windowed/full-screen mode

// Configure DX feature level
D3D_FEATURE_LEVEL featureLevels[] =
{
    D3D_FEATURE_LEVEL_11_1,
    D3D_FEATURE_LEVEL_11_0,
    D3D_FEATURE_LEVEL_10_1,
    D3D_FEATURE_LEVEL_10_0
};
UINT numFeatureLevels = ARRAYSIZE(featureLevels);

char devname_dx[128];
bool device_ok = getAdapter(&adapter, devname_dx);

DXGI_ADAPTER_DESC adapterDesc;
adapter->GetDesc(&adapterDesc);
std::cout << "DirectX GPU " << devname_dx << " : [BusID " << adapterDesc.DeviceId << " | DevID " << adapterDesc.SubSysId << "]" << std::endl;

// Create a device, device context and swap chain using the information in the scd struct
hr = D3D11CreateDeviceAndSwapChain(
    adapter,                    // graphics adapter, which was already checked for CUDA support
    D3D_DRIVER_TYPE_UNKNOWN,    // If adapter is not NULL, we need to use UNKNOWN
    NULL,                       // software
    NULL,                       // flags 
    featureLevels,              // D3D features to enable
    numFeatureLevels,           // D3D feature count
    D3D11_SDK_VERSION,          // D3D SDK version (here 11)
    &swapchainDesc,             // swap chain description
    &swapchain,                 // swap chain
    &device,                    // D3D device
    NULL,                       // supported feature level
    &device_context);           // D3D device context
if (FAILED(hr))
{
    std::string msg = std::string("Failed to create DX device and swap chain: ") + std::to_string(hr);
    throw std::exception(msg.c_str());
}

// 释放适配器
adapter->Release();

// 获取设备上下文
device->GetImmediateContext(&device_context);

// 获取交换链的后台缓冲区纹理
hr = swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&texture_rgb);

// 创建渲染目标视图
hr = device->CreateRenderTargetView(texture_rgb, nullptr, &rtv);

我需要创建一个与texture_rgb属性匹配的暂存纹理(STAGING),用于查询像素数据并后续与CUDA集成。我尝试获取texture_rgb的描述,仅修改Usage为D3D11_USAGE_STAGING后创建纹理:

D3D11_TEXTURE2D_DESC texture_rgb_debugDesc;
texture_rgb->GetDesc(&texture_rgb_debugDesc);

// 仅修改Usage字段
texture_rgb_debugDesc.Usage = D3D11_USAGE::D3D11_USAGE_STAGING;

ID3D11Texture2D* texture_rgb_debug = nullptr;
hr = device->CreateTexture2D(&texture_rgb_debugDesc, nullptr, &texture_rgb_debug);

但执行时DirectX报错:

E_INVALIDARG One or more arguments are invalid.

将Usage改回D3D11_USAGE_DEFAULT则纹理可正常创建,请问如何解决这个问题?

解决方案

创建暂存纹理(D3D11_USAGE_STAGING)时,仅修改Usage字段是不够的,还需要调整以下两个关键参数——暂存纹理的使用规则与渲染目标纹理存在本质差异:

  1. 清空绑定标志(BindFlags):暂存纹理不能绑定到任何渲染管线阶段(比如作为渲染目标),必须将BindFlags设置为0。交换链的后台缓冲区纹理默认带有D3D11_BIND_RENDER_TARGET标志,直接复用该描述会导致参数冲突。
  2. 设置CPU访问权限(CPUAccessFlags):暂存纹理的核心用途是CPU与GPU之间的数据传输,必须指定CPU的访问权限,比如D3D11_CPU_ACCESS_READ(用于从GPU读取数据到CPU)或D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE(双向访问)。

修改后的创建代码如下:

D3D11_TEXTURE2D_DESC texture_rgb_debugDesc;
texture_rgb->GetDesc(&texture_rgb_debugDesc);

// 调整暂存纹理所需的参数
texture_rgb_debugDesc.Usage = D3D11_USAGE_STAGING;
texture_rgb_debugDesc.BindFlags = 0; // 暂存纹理不能有绑定
texture_rgb_debugDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; // 根据需求选择读写权限

// 可选:如果原纹理是多重采样(SampleDesc.Count > 1),需将暂存纹理设置为非多重采样
// texture_rgb_debugDesc.SampleDesc.Count = 1;
// texture_rgb_debugDesc.SampleDesc.Quality = 0;

ID3D11Texture2D* texture_rgb_debug = nullptr;
hr = device->CreateTexture2D(&texture_rgb_debugDesc, nullptr, &texture_rgb_debug);
if (FAILED(hr))
{
    // 处理错误逻辑
}

修改完成后,即可成功创建与原纹理尺寸、格式匹配的暂存纹理。后续可通过ID3D11DeviceContext::CopyResource将原纹理的数据复制到暂存纹理,再调用Map方法获取CPU可访问的指针来读取像素数据。

内容的提问来源于stack exchange,提问作者rbaleksandar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 09:17:25