c++ 如何创建一个staging ID3D11Texture2D纹理?

oxcyiej7  于 2023-10-20  发布在  其他
关注(0)|答案(2)|浏览(121)

我使用以下代码创建了一个交换链:

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 DXGI_FORMAT_R8G8B8A8_UNORM DXGI_FORMAT_R32G32B32_FLOAT
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 (1-4, above is not guaranteed for DX11 GPUs)
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); //devid = 9436, subsysid = 177803304
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, otherwise use D3D_DRIVER_TYPE_HARDWARE
    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 (use DXGI_ADAPTER_DESC variable to retrieve the information, e.g. &featureLevel)
    &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);

我将2D纹理texture_rgbMap为唯一的缓冲区

hr = swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&texture_rgb);

由我的呈现目标视图使用

hr = device->CreateRenderTargetView(texture_rgb, nullptr, &rtv);

我想创建一个舞台2D纹理。目前,它将只用于查找一些像素数据,但稍后我会将其与CUDA集成。它反映了我的texture_rgb的内容-尺寸,颜色格式,像素数据等。
为此,我检索texture_rgb的描述

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

只修改D3D11_TEXTURE2D_DESC::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一个或多个参数无效。
如果我将D3D11_TEXTURE2D_DESC::Usage更改为初始值(此处为D3D11_USAGE_DEFAULT),则纹理将毫无问题地创建。

kognpnkq

kognpnkq1#

从交换链获得的纹理应该具有D3D11_BIND_RENDER_TARGET绑定标志,而使用D3D11_USAGE_STAGING的纹理不能用作任何渲染阶段的输入或输出,因此与D3D11_BIND_RENDER_TARGET标志不兼容。你应该覆盖纹理描述中的所有字段,除了尺寸和格式。

brvekthn

brvekthn2#

分段纹理不能绑定在管道的任何阶段中,因此BindFlags应为0。
您还需要像以前一样设置使用情况。最后一部分,因为你想把数据读回CPU,也是为了覆盖CPU标志:

ID3D11Texture2D* texture_rgb; //your swapchain

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

texture_rgb_debugDesc.BindFlags = 0; //needed as no bind flags are allowed
texture_rgb_debugDesc.CPUAccessFlags = D3D11_CPU_ACCESS_FLAG::D3D11_CPU_ACCESS_READ;
texture_rgb_debugDesc.Usage = D3D11_USAGE_STAGING;

另请注意,多采样纹理不能创建为分段,因此如果您希望支持此功能,则还需要首先解析为非多采样资源,然后执行复制操作。
要与CUDA集成,您根本不需要暂存资源,您可以直接使用渲染目标进行互操作。
此外,为了捕获这些错误,您应该在创建设备时使用D3D11_CREATE_DEVICE_DEBUG标志。

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, otherwise use D3D_DRIVER_TYPE_HARDWARE
NULL,                       
D3D11_CREATE_DEVICE_DEBUG,  // flags (make this conditional)
featureLevels,              
numFeatureLevels,          
D3D11_SDK_VERSION,          
&swapchainDesc,                     // swap chain description
&swapchain,                 // swap chain
&device,                    // D3D device
NULL,                       // supported feature level (use . 
&featureLevel)
&device_context);

这将在visual studio调试输出窗口中出现错误时给予更有意义的错误消息(相对于invalidargs,它没有太大帮助)。

相关问题