跨进程共享ID3D11Texture2D触发E_INVALIDARG错误求助
我尝试使用命名共享句柄在进程间共享ID3D11Texture2D,线程内测试可正常运行,但在两个独立应用间执行相同操作时返回E_INVALIDARG错误,表现类似纹理未正确创建或共享配置有误(比如纹理未设置正确标志时创建句柄也会出现该错误)。
句柄创建代码
D3D11_TEXTURE2D_DESC texDesc; _tex->GetDesc( &texDesc ); // check if can be shared if ( !( texDesc.MiscFlags & D3D11_RESOURCE_MISC_SHARED ) || !( texDesc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_NTHANDLE ) ) { return -1; } IDXGIResource1 *dxgiResource = nullptr; auto result = _tex->QueryInterface( IID_PPV_ARGS( &dxgiResource ) ); if ( FAILED( result ) ) { return -1; } // convert name to wide string auto wHandleName = ToWString( handleName ); result = dxgiResource->CreateSharedHandle( NULL, DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE, wHandleName.c_str(), &_sharedHandle ); } dxgiResource->Release(); if ( FAILED( result ) ) { return -1; }
句柄打开代码
ID3D11Texture2D *sharedTexture; auto result = d3d11Device1->OpenSharedResourceByName( ToWString( handleName ).c_str(), DXGI_SHARED_RESOURCE_READ, IID_PPV_ARGS( &sharedTexture ) ); // this is where the error happens if ( FAILED( result ) ) { return nullptr; } DEFER( { sharedTexture->Release(); } );
我会保留纹理和句柄直到被其他进程获取并释放,线程间测试代码运行正常。文档说明无需使用DuplicateHandle,仅使用名称即可。请问我遗漏了什么?
以下是几个可能导致E_INVALIDARG的关键遗漏点:
纹理创建时必须提前设置共享标志
你的代码只是检查已创建纹理的MiscFlags,但如果纹理创建阶段没有同时设置D3D11_RESOURCE_MISC_SHARED和D3D11_RESOURCE_MISC_SHARED_NTHANDLE,后续的检查和句柄创建都会隐含问题。必须在初始化D3D11_TEXTURE2D_DESC时就将这两个标志加入MiscFlags,才能支持命名共享句柄。确保设备版本符合要求
OpenSharedResourceByName是ID3D11Device1的方法,打开句柄的进程必须使用ID3D11Device1或更高版本的设备。创建设备时要确保启用DXGI 1.2及以上特性,比如调用D3D11CreateDevice时指定D3D11_CREATE_DEVICE_BGRA_SUPPORT,或者检查设备是否能成功查询到ID3D11Device1接口。共享句柄名称需全局唯一且格式正确
命名共享句柄的名称如果与系统内其他内核对象重名,会导致创建或打开失败。建议使用带前缀的唯一名称,比如Local\MyApp_SharedTexture_001(Local\前缀适用于当前用户会话内的进程共享,跨会话或服务与应用共享用Global\)。同时要验证ToWString函数是否正确完成字符串转换,避免出现空字符串或乱码。权限参数需合法且匹配范围
创建句柄时指定的权限(DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE)要确保合法,打开句柄时请求的权限不能超出创建时的范围。虽然你这里打开时仅请求读权限是合法的,但如果创建时的权限参数传错(比如用了未定义的常量),也会触发E_INVALIDARG。验证资源生命周期与接口查询结果
确保创建共享句柄的原纹理对象在另一个进程完成句柄打开前始终存活,不能提前释放。同时要确认QueryInterface获取IDXGIResource1的操作确实成功,有些特殊纹理类型可能不支持该接口,需检查返回的HRESULT具体值(而非仅判断FAILED)。检查设备的共享资源支持等级
可以通过ID3D11Device::CheckFeatureSupport查询D3D11_FEATURE_DATA_D3D11_OPTIONS中的SharedResourceTier,确保至少为Tier 1(大部分现代显卡都支持),如果等级不足,也会导致共享操作失败。
内容的提问来源于stack exchange,提问作者BartW

