DirectX - отказано в доступе при создании цепочки подкачки для CoreWindow

В настоящее время я пытаюсь создать цепочку подкачки для CoreWindow, используя последнюю версию SharpDX в качестве оболочки DirectX и UWP в качестве базовой структуры проекта.

Документация по этому поводу настолько скудна, что это невероятно. Тем не менее я смог найти фрагмент, который выглядел многообещающим. Изначально я всегда получал сообщение об ошибке E_INVALIDCALL. Теперь "только" E_ACCESSDENIED.

Пока что я сделал это, чтобы настроить цепочку:

var description = new SwapChainDescription1
{
    BufferCount = 2,
    Flags = SwapChainFlags.None,
    SampleDescription = new SampleDescription(1, 0),
    SwapEffect = SwapEffect.FlipSequential,
    Usage = Usage.RenderTargetOutput,
    Width = 0,
    Height = 0,
    Scaling = Scaling.None,
    Format = Format.B8G8R8A8_UNorm,
    Stereo = false
};

CoreWindow window = CoreWindow.GetForCurrentThread();
if (window == null)
{
    Logging.Error("Could not retrieve core window for swap chain.");
    throw new Exception("Invalid core window.");
}

using (var device = _device.QueryInterface<SharpDX.DXGI.Device2>())
{
    device.MaximumFrameLatency = 1;
    using (Adapter adapter = device.Adapter)
    {
        using (ComObject coreWindow = new ComObject(window))
        {
            using (Factory2 factory = adapter.GetParent<Factory2>())
                _swapChain = new SwapChain1(factory, _device, coreWindow, ref description);
        }
    }
}

Конструктор SwapChain1 выдает исключение SharpDX:

SharpDX.Result.CheckError () SharpDX.DXGI.Factory2.CreateSwapChainForCoreWindow (ComObject deviceRef, ComObject windowRef, SwapChainDescription1 & descRef, выход restrictToOutputRef, SwapChain1 swapChainOut) SharpDX.DXGI.SwapChain1..ctor (Factory2 завод, ComObject устройство, ComObject coreWindow, SwapChainDescription1 & описание , Вывод restrictToOutput) RobInspect.Visualizer.Rendering.RenderingPanel.InitializeSizeDependentResources () RobInspect.Visualizer.Rendering.RenderingPanel.InitializeDevice ()

«HRESULT: [0x80070005], модуль: [General], ApiCode: [E_ACCESSDENIED / общая ошибка отказа в доступе], сообщение: доступ запрещен».

Кто-нибудь может мне объяснить, почему? «Доступ запрещен» - довольно широкое утверждение, и я не слишком разбираюсь во внутренностях DirectX.

Дополнительная информация: Код выполняется в основном (UI) потоке. Поэтому я полагаю, что могу исключить, что ссылка на CoreWindow недоступна. Поскольку это первоначальная инициализация, я также исключаю возможность того, что объекты DirectX не будут освобождены должным образом перед созданием цепочки подкачки.

ИЗМЕНИТЬ: это код для создания устройства. В то время как флаги установлены на DeviceCreationFlags.BgraSuuport и DeviceCreationFlags.Debug. Установлены уровни от FeatureLevel.Level_11_1 до FeatureLevel.Level_9_1.

using (var device = new Device(DriverType.Hardware, flags, levels))
{
    _device = device.QueryInterface<Device1>();
    _context = _device.ImmediateContext1;
}

person SharpShade    schedule 26.02.2018    source источник
comment
Вам действительно нужен SharpDX? Может, Win2d выполнит ваши замыслы? Это легкая оболочка Direct2D C #.   -  person Jet Chopper    schedule 26.02.2018
comment
Я успешно запустил код в пустом проекте UWP без каких-либо проблем. Конструктор SwapChain1 работает без исключений. Как вы создаете экземпляр устройства?   -  person Mehrzad Chehraz    schedule 27.02.2018
comment
Так как мне нужно визуализировать 3D-модель в реальном времени, да, я это делаю. Хорошо, это странно ... Я использую конструктор using (var device = new SharpDX.Direct3D11.Device(Hardware, flags, levels)), а затем запрашиваю Device1 (не уверен - обновлю это примерно через час, когда буду на работе). Уровни установлены от 11_1 до 9_3. Для флагов установлено значение BgraSupport и Debug.   -  person SharpShade    schedule 27.02.2018
comment
Обновил. Я просто попробовал это в новом проекте и тоже запустил. Теперь вопрос цены: почему это не работает. Думаю, я могу исключить объекты SharpDX в качестве источника. Возможным источником проблемы может быть экземпляр CoreWindow. Я использую пакет DevExpress, в котором я обнаружил, что они, кажется, используют SharpDX или DirectX для внутреннего рендеринга определенных вещей. По крайней мере, я нашел похожие классы. Может быть, это блокировка? Но обычно все-таки можно создать и назначить несколько цепочек подкачки.   -  person SharpShade    schedule 27.02.2018
comment
Хорошо. Прибил его к CoreWindow. Создав новое представление и используя его окно, я могу без проблем создать цепочку подкачки.   -  person SharpShade    schedule 27.02.2018
comment
Хорошо. После включения встроенной отладки я обнаружил, что источником проблемы является исключение, в котором говорится: DCOMPOSITION_ERROR_WINDOW_ALREADY_COMPOSED. Поэтому я подумал, что проблема в том, что я инициализирую устройство после запуска приложения на какой-то странице. Я попробовал запустить код в методе запуска приложения, и теперь он работает. Думаю, решение состоит в том, чтобы создать устройство при запуске и назначить его позже, когда оно вам понадобится.   -  person SharpShade    schedule 27.02.2018
comment
@MehrzadChehraz вы действительно запускали проект, пока не было видно представление? В моем тестовом проекте я столкнулся с той же проблемой, что и в моем проекте: он создает объекты DX, но вызывает исключение без трассировки стека, в котором говорится: DCOMPOSITION_ERROR_WINDOW_ALREADY_COMPOSED.   -  person SharpShade    schedule 27.02.2018
comment
Я получаю ту же ошибку. Дополнительную информацию об этой ошибке можно найти здесь. Возможно, вам потребуется создать еще один вопрос для этой проблемы.   -  person Mehrzad Chehraz    schedule 27.02.2018
comment
Наконец нашел решение. Я отправлю его как ответ, чтобы он был хорошо виден другим.   -  person SharpShade    schedule 27.02.2018
comment
Я иногда получаю эту ошибку, казалось бы, случайно при воссоздании цепочки подкачки, но мое приложение вообще не использует XAML, это чистый C ++ / CX в UWP. Вы случайно не нашли какие-либо ресурсы, не относящиеся к XAML, связанные с этой ошибкой?   -  person LB--    schedule 25.05.2020
comment
@ LB-- Нет, прости. Думаю, особой разницы быть не должно, поскольку WinRT / XAML также в основном является родным.   -  person SharpShade    schedule 26.05.2020


Ответы (1)


Решение этой проблемы состоит в том, что термины WinRT Core и WinRT XAML вводят в заблуждение. Поскольку UWP основан на CoreWindow и оба поддерживают и используют их, непонятно, где что использовать.

DirectX предоставляет два метода для WinRT и один для Desktop. Один Factory2.CreateSwapChainForCoreWindow(...) и один Factory2.CreateSwapChainForComposition(...). Разница в том, что один принимает CoreWindow как параметр, а другой нет. И вот в какую ловушку я попал.

Core обозначает схему проектирования, в которой используются только IFrameworkView и IFrameworkViewSource (см. здесь для примера с SharpDX), тогда как XAML обозначает традиционную схему, в которой у вас есть класс Windows.UI.Xaml.Application.

При использовании Core-модели необходимо вызвать метод ...ForCoreWindow(...) для создания цепочки подкачки. При использовании подхода на основе XAML вам понадобится цепочка подкачки композиции. Я для себя уже пробовал это, но потерпел неудачу, потому что я забыл включить (совет: сделайте это, если еще не сделано) встроенную отладку, поэтому уровень отладки DirectX фактически показал мне важную информацию, которая могла бы сэкономить мне часы, если не дни проб и ошибок.

Проблема здесь в том, что и композиция, и цепочки подкачки CoreWindow требуют специальных настроек в SwapChainDescription1. Я оставлю вам документация MSDN. Более того, если включена собственная отладка и уровень отладки, DirectX сообщит вам, какой именно параметр является недопустимым.

person SharpShade    schedule 27.02.2018