在原生Direct3D 11 DLL中使用Unity纹理遇DEVICE_OPEN_SHARED_RESOURCE_INVALIDARG_RETURN错误
DX11 Unity应用与原生C++ DLL共享纹理失败问题
问题背景
我有一个DX11模式的Unity应用,加载了自定义原生C++ DLL,该DLL创建了独立的D3D11 Device。现在需要无需拷贝CPU内存,直接在C++ DLL中使用Unity的RenderTexture,但调用OpenSharedResource1时失败。
Unity端代码
MyNativeLib.SetBuffers11(srcTexture.GetNativeTexturePtr());
注:srcTexture为Unity的RenderTexture对象
原生C++ DLL代码
void SetBuffers11(ID3D11Resource* colorRes) { D3D11_TEXTURE2D_DESC texDesc; ID3D11Texture2D* tempColor; colorRes->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&tempColor); tempColor->GetDesc(&texDesc); // 此步骤正常执行,能获取正确描述 ID3D11Resource* tempResource; HRESULT openResult = m_device->OpenSharedResource1( colorRes, __uuidof(ID3D11Resource), (void**)&tempResource); // 此步骤失败 tempResource->QueryInterface(__uuidof(ID3D11Texture2D), (void**)(&tempColor)); tempColor->GetDesc(&texDesc); }
错误信息
- 尝试访问纹理数据时,触发错误:
MISCELLANEOUS CORRUPTION #18: CORRUPTED_PARAMETER - 调用
OpenSharedResource失败,提示指针为NT类型,建议使用OpenSharedResource1;但调用OpenSharedResource1返回E_INVALIDARG,对应D3D11错误日志:
D3D11 ERROR: ID3D11Device::OpenSharedResource1: Returning E_INVALIDARG, meaning invalid parameters were passed. [ STATE_CREATION ERROR #381: DEVICE_OPEN_SHARED_RESOURCE_INVALIDARG_RETURN]
查询到的纹理描述
Format : 0x09 (DXGI_FORMAT_R16G16B16A16_TYPELESS) Bind Flags : 0x20 | 0x08 (D3D11_BIND_SHADER_RESOURCE and D3D11_BIND_RENDER_TARGET) CPU ACCESS : 0
解决方案
核心问题原因
直接传递ID3D11Resource*给OpenSharedResource1是错误的,该函数需要的是共享资源的句柄(HANDLE),而非资源指针本身。Unity返回的GetNativeTexturePtr()是D3D资源的指针,但跨设备/进程共享资源必须通过句柄实现。
修复步骤
Unity端获取共享句柄:
Unity的RenderTexture默认不会生成共享句柄,需要手动开启共享属性并通过Unity的DX11图形API获取句柄:using System; using System.Runtime.InteropServices; using UnityEngine; public class TextureShare : MonoBehaviour { [DllImport("MyNativeLib")] private static extern void SetBuffers11(IntPtr sharedHandle); public RenderTexture srcTexture; private void Start() { // 确保RenderTexture开启共享标志 srcTexture.creationFlags = RenderTextureCreationFlags.Shared; srcTexture.Create(); // 获取D3D11纹理的共享句柄 IntPtr nativeTexPtr = srcTexture.GetNativeTexturePtr(); IntPtr sharedHandle = IntPtr.Zero; NativeMethods.UnityGraphicsD3D11GetSharedHandle(nativeTexPtr, ref sharedHandle); if (sharedHandle != IntPtr.Zero) { SetBuffers11(sharedHandle); } } } internal static class NativeMethods { [DllImport("UnityGraphicsD3D11")] public static extern int UnityGraphicsD3D11GetSharedHandle(IntPtr d3dResource, ref IntPtr outSharedHandle); }C++ DLL端修改代码:
接收共享句柄,调用OpenSharedResource1打开共享资源:void SetBuffers11(HANDLE sharedHandle) { if (!sharedHandle) { return; } ID3D11Resource* tempResource = nullptr; HRESULT openResult = m_device->OpenSharedResource1( sharedHandle, __uuidof(ID3D11Resource), (void**)&tempResource); if (SUCCEEDED(openResult)) { ID3D11Texture2D* tempColor = nullptr; tempResource->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&tempColor); if (tempColor) { D3D11_TEXTURE2D_DESC texDesc; tempColor->GetDesc(&texDesc); // 后续可创建ShaderResourceView等访问纹理数据 tempColor->Release(); } tempResource->Release(); } }
额外注意事项
- 确保Unity的D3D设备和DLL的D3D设备共享同一适配器(Adapter),否则无法跨设备共享资源。创建DLL的D3D设备时,可复用Unity的适配器信息,或开启
D3D11_CREATE_DEVICE_BGRA_SUPPORT等必要标志。 - 目标纹理为
TYPELESS格式,后续创建ShaderResourceView时需指定具体格式(如DXGI_FORMAT_R16G16B16A16_FLOAT)。 - 严格管理COM对象的释放,避免内存泄漏。
内容的提问来源于stack exchange,提问作者molnarriso
相关产品推荐
相关产品推荐

