Unity:CopyTexture到外部texture2D
Unity: CopyTexture to External texture2D
我需要将 Unity texture/Rendertexture 公开给某些原生插件,这需要纹理上的“D3D11_RESOURCE_MISC_SHARED”标志。
unity创建的纹理没有这个标志,所以,我从插件端创建它,然后使用CreateExternalTexture在unity中创建一个参考纹理,并使用[=33=将内容复制到这个原生纹理中].
2 个纹理具有相同的维度、相同的大小、相同的格式和相同的 mipCount(0)
问题是,当我在 unity 中显示它(用于调试目的)时,我什么也看不到,也没有发生错误。
顺便说一句,如果我通过 ReadPixel 复制,会发生错误:
ReadPixels 在未定义图像 0 上调用(有效值为 0 - -1
如果我使用unity创建纹理api,CopyTexture成功并且可以看到结果。但是后来,我丢失了“D3D11_RESOURCE_MISC_SHARED”标志。
所以,也许我创建的纹理无效?
我的代码:
D3D11_TEXTURE2D_DESC desc = { 0 };
desc.Width = width;
desc.Height = height;
desc.MipLevels = 0;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;//这里,格式能不能调整?比如,A8是需要的吗?
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;//普通资源
//desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;//应该不需要cpu访问的,不是read也不是write
desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;//for "OpenSharedHandle" d3d11 api
HRESULT hr = E_FAIL;
if (FAILED(hr = pDevice->CreateTexture2D(&desc, nullptr, &g_unityEquirectTexture)))
{
Log(" Create Shared Texture Failed!");
return NULL;
}
Log("CreateSharedTexture success");
//return g_unityEquirectTexture;
Unity CopyTexture代码:
if (output == null)
{
Debug.Log($"limit = {QualitySettings.masterTextureLimit}");
//output = new Texture2D(equirect.width, equirect.height, TextureFormat.RGBA32,false);//uncomment this line and then copyTexture below succeeds
IntPtr externalTextureData = CGDKInterOp.cgdk_c_CreateExternalTexture(equirectLeft.GetNativeTexturePtr(), equirectLeft.width * 2, equirectLeft.height);
if (externalTextureData != IntPtr.Zero)
{
output = Texture2D.CreateExternalTexture(equirectLeft.width * 2, equirectLeft.height, TextureFormat.RGBA32, false, true, externalTextureData);
}
}
if (output == null)
{
Debug.LogError("create texture from external failed!");
return;
}
//RenderTexture.active = equirect;
//output.ReadPixels(new Rect(0, 0, equirect.width, equirect.height), 0, 0);
//RenderTexture.active = null;
Graphics.CopyTexture(equirect, output);
对此可能有更好的解决方案,但上次我需要将纹理数据从本机端复制到托管 (Unity) 时,我通过数据编组完成了。
你基本上只需要在本机插件中公开一个方法来将纹理数据作为数组传递给你,然后在 C# 代码中有一个方法来获取它的数据(通过调用该方法),释放指针到完成后的本机内存。您可以在 Microsoft 的文档中找到有关编组和互操作的信息(例如 https://docs.microsoft.com/en-us/dotnet/framework/interop/marshalling-different-types-of-arrays)。
如果你的纹理总是保证具有相同的大小和格式,那就更容易了——但如果你需要知道一些额外的参数,以便你知道纹理应该如何在 managed-land 中表示,你总是可以传递给自己通过相同的方法附加数据。
好的,自己解决了
问题是:Miplevel == 0.this 导致 d3d11 创建一个纹理 0B 内存分配 !
将 Miplevel 更改为 1 解决了问题
注意:
在unity inspector中,我们可以看到纹理分配的内存。我发现我的纹理有来自检查器的 0B 内存,然后,我使用这个线索搜索并找到了解决方案
我需要将 Unity texture/Rendertexture 公开给某些原生插件,这需要纹理上的“D3D11_RESOURCE_MISC_SHARED”标志。
unity创建的纹理没有这个标志,所以,我从插件端创建它,然后使用CreateExternalTexture在unity中创建一个参考纹理,并使用[=33=将内容复制到这个原生纹理中].
2 个纹理具有相同的维度、相同的大小、相同的格式和相同的 mipCount(0)
问题是,当我在 unity 中显示它(用于调试目的)时,我什么也看不到,也没有发生错误。
顺便说一句,如果我通过 ReadPixel 复制,会发生错误:
ReadPixels 在未定义图像 0 上调用(有效值为 0 - -1
如果我使用unity创建纹理api,CopyTexture成功并且可以看到结果。但是后来,我丢失了“D3D11_RESOURCE_MISC_SHARED”标志。
所以,也许我创建的纹理无效? 我的代码:
D3D11_TEXTURE2D_DESC desc = { 0 };
desc.Width = width;
desc.Height = height;
desc.MipLevels = 0;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;//这里,格式能不能调整?比如,A8是需要的吗?
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;//普通资源
//desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;//应该不需要cpu访问的,不是read也不是write
desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;//for "OpenSharedHandle" d3d11 api
HRESULT hr = E_FAIL;
if (FAILED(hr = pDevice->CreateTexture2D(&desc, nullptr, &g_unityEquirectTexture)))
{
Log(" Create Shared Texture Failed!");
return NULL;
}
Log("CreateSharedTexture success");
//return g_unityEquirectTexture;
Unity CopyTexture代码:
if (output == null)
{
Debug.Log($"limit = {QualitySettings.masterTextureLimit}");
//output = new Texture2D(equirect.width, equirect.height, TextureFormat.RGBA32,false);//uncomment this line and then copyTexture below succeeds
IntPtr externalTextureData = CGDKInterOp.cgdk_c_CreateExternalTexture(equirectLeft.GetNativeTexturePtr(), equirectLeft.width * 2, equirectLeft.height);
if (externalTextureData != IntPtr.Zero)
{
output = Texture2D.CreateExternalTexture(equirectLeft.width * 2, equirectLeft.height, TextureFormat.RGBA32, false, true, externalTextureData);
}
}
if (output == null)
{
Debug.LogError("create texture from external failed!");
return;
}
//RenderTexture.active = equirect;
//output.ReadPixels(new Rect(0, 0, equirect.width, equirect.height), 0, 0);
//RenderTexture.active = null;
Graphics.CopyTexture(equirect, output);
对此可能有更好的解决方案,但上次我需要将纹理数据从本机端复制到托管 (Unity) 时,我通过数据编组完成了。
你基本上只需要在本机插件中公开一个方法来将纹理数据作为数组传递给你,然后在 C# 代码中有一个方法来获取它的数据(通过调用该方法),释放指针到完成后的本机内存。您可以在 Microsoft 的文档中找到有关编组和互操作的信息(例如 https://docs.microsoft.com/en-us/dotnet/framework/interop/marshalling-different-types-of-arrays)。 如果你的纹理总是保证具有相同的大小和格式,那就更容易了——但如果你需要知道一些额外的参数,以便你知道纹理应该如何在 managed-land 中表示,你总是可以传递给自己通过相同的方法附加数据。
好的,自己解决了
问题是:Miplevel == 0.this 导致 d3d11 创建一个纹理 0B 内存分配 ! 将 Miplevel 更改为 1 解决了问题
注意: 在unity inspector中,我们可以看到纹理分配的内存。我发现我的纹理有来自检查器的 0B 内存,然后,我使用这个线索搜索并找到了解决方案