Мне нужно предоставить текстуру/Rendertexture Unity для некоторого собственного плагина, для которого требуется флаг «D3D11_RESOURCE_MISC_SHARED» на текстуре.
текстуры, созданные единством, не имеют этого флага, поэтому я создал его со стороны плагина, а затем создал эталонную текстуру в единстве, используя CreateExternalTexture, и скопировал содержимое в эту нативную текстуру, используя Graphics.CopyTexture.
2 текстуры имеют одинаковый размер, одинаковый размер, один и тот же формат и один и тот же mipCount (0)
проблема в том, что когда я показываю это в единстве (в целях отладки), я ничего не вижу и ошибок не возникает.
Кстати, если я копирую ReadPixel, возникает ошибка:
ReadPixels вызывается для неопределенного изображения 0 (допустимые значения: 0 - -1
если я создаю текстуру с помощью API Unity, 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-other-types-of-arrays). Если ваша текстура всегда гарантированно будет одного размера и формата, это проще - но если вам нужно знать какие-то дополнительные параметры, чтобы вы знали, как Текстура должна быть представлена в управляемом-земле, вы всегда можете передать себе дополнительные данные через тот же метод.
Хорошо, решил сам.
проблема в следующем: Miplevel == 0. Это приводит к тому, что d3d11 создает текстуру с выделено памяти 0B! изменение Miplevel на 1 решило проблему
примечание: В инспекторе единства мы можем видеть память, выделенную текстурами. Я обнаружил, что моя текстура имеет память 0B из инспектора, а затем я провел поиск, используя эту подсказку, и нашел решение.