DispatchRays жалуется на (не)правильную кучу дескрипторов

Я пытаюсь запустить вычислительный шейдер перед переключением на конвейер трассировки лучей в DirectX 12, поэтому у меня есть два разных состояния конвейера. Один для вычислительного шейдера и один для трассировки лучей. Раньше конвейер трассировки лучей работал хорошо, но теперь я пытаюсь использовать вычислительный шейдер для генерации шума для окружающего затенения и сохранения его в текстуре, а затем копирую текстуру в кучу дескрипторов, используемую конвейером трассировки лучей. Но после переключения обратно на конвейер трассировки лучей и выполнения вызова DispatchRays я получаю следующую ошибку:

D3D12 ERROR: ID3D12CommandList::DispatchRays: The descriptor heap (0x0000012094789250:'Compute Heap') containing handle 0x1868acf14000000 is different from currently set descriptor heap 0x0000012094787CE0:'DXR Heap'. [ EXECUTION ERROR #554: SET_DESCRIPTOR_HEAP_INVALID]

Мои кучи дескрипторов выглядят так:

Noise heap:
1 - UAV for a 2D texture

DXR heap:
1 - UAV for 2D texture for output
2 - SRV for TLAS
3 - CBV for camera properties
4 - CBV for light properties
5 - SRV for material data
6 - UAV for noise 2D texture

Вот что я пытался сделать для рендеринга:

commandList->SetPipelineState(computeShaderState);
commandList->SetComputeRootSignature(computeShaderSignature);
commandList->SetDescriptorHeaps(1, &computeHeap);
commandList->SetComputeRootDescriptorTable(0, computeHeap->GetGPUDescriptorHandleForHeapStart());

// calculate dispatch args
UINT xwidth = static_cast<UINT>(ceil(texWidth / 32.f));
UINT xheight = static_cast<UINT>(ceil(texHeight / 32.f));
commandList->Dispatch(xwidth, xheight, 1);

// copy texture from computeHeap resource to dxrHeap resource

// switch to DXR pipeline
commandList->SetPipelineState1(dxrState);
commandList->SetDescriptorHeaps(1, &dxrHeap);

// transition output texture
// compute dispatch-rays description

commandList->DispatchRays(&dxrDesc); // <- this line throws error

// switch to raster-pipeline to draw ImGUI
commandList->SetPipelineState(rasterState);
commandList->SetDescriptorHeaps(1, &rasterHeap);
// draw ImGui stuff

Есть две вещи, которые меня смущают: во-первых, ошибка, которую я получаю от вызова диспетчеризации лучей, жалуется на то, что вычислительная куча отличается от текущей установленной кучи, которая является кучей DXR. Но на этом этапе я хочу, чтобы куча DXR была установлена, поскольку в ней есть все ресурсы, необходимые для трассировки лучей. Во-вторых, раньше мне удавалось переключаться между трассировкой лучей и растром для графического интерфейса, но теперь, когда я пытаюсь также переключиться между состоянием вычислений, я получаю вышеупомянутую ошибку.

Я нашел этот старый пост, в котором есть аналогичная ошибка, но в этом посте текущая куча дескрипторов равна нулю, а у меня нет, и я считаю, что мой код выше соответствует ответу Чака Уолборна на этот пост.

В идеале я хочу, чтобы вычислительный шейдер отправлялся и записывал в текстуру. Затем я хочу скопировать указанную текстуру в другую текстуру, которая принадлежит другой куче дескрипторов, чтобы я мог использовать текстуру, сгенерированную из моего вычислительного шейдера, внутри моего шейдера попадания для лучшей случайности во вторичных лучах.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
132
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вам нужно снова установить таблицу корневых дескрипторов вычислений, но указать на кучу dxr - потому что та, которая была ранее установлена, указывает на другую кучу дескрипторов, поэтому в основном снова устанавливается таблица, содержащая БПЛА, за исключением она находится в другой куче, вот так:

commandList->SetPipelineState(computeShaderState);
commandList->SetComputeRootSignature(computeShaderSignature);
commandList->SetDescriptorHeaps(1, &computeHeap);
commandList->SetComputeRootDescriptorTable(0, computeHeap->GetGPUDescriptorHandleForHeapStart());

// calculate dispatch args
UINT xwidth = static_cast<UINT>(ceil(texWidth / 32.f));
UINT xheight = static_cast<UINT>(ceil(texHeight / 32.f));
commandList->Dispatch(xwidth, xheight, 1);

// copy texture from computeHeap resource to dxrHeap resource

// switch to DXR pipeline
commandList->SetPipelineState1(dxrState);
commandList->SetDescriptorHeaps(1, &dxrHeap);


// HERE ; !!! dont forget to use your/correct root parameter index etc :^)
commandList->SetComputeRootDescriptorTable(0, dxrHeap->GetGPUDescriptorHandleForHeapStart());


// transition output texture
// compute dispatch-rays description

commandList->DispatchRays(&dxrDesc);

// switch to raster-pipeline to draw ImGUI
commandList->SetPipelineState(rasterState);
commandList->SetDescriptorHeaps(1, &rasterHeap);
// draw ImGui stuff

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

В идеале я хочу, чтобы вычислительный шейдер отправлялся и записывал в текстуру. Затем я хочу скопировать указанную текстуру в другую текстуру, которая принадлежит другой куче дескрипторов, чтобы я мог использовать текстуру, сгенерированную из моего вычислительного шейдера, внутри моего шейдера попадания для лучшей случайности во вторичных лучах.

Самый простой способ - просто при инициализации вашего приложения создать второй БПЛА, используя метод CreateUnorderedAccessView, или/и использовать уже существующую кучу, поскольку ваша корневая подпись в любом случае выглядит одинаковой - поэтому используйте одну кучу как для вычислительного шейдера, так и для представлений шейдера dxr (возможно даже графика), чтобы избежать дублирования изображений.

Возможно, можно было бы использовать метод CopyDescriptors, но мне неясно, как он работает, и в данной ситуации это просто излишне.

(В зависимости от дизайна вам также может потребоваться использовать SetGraphicsRootDescriptorTable в проходе отрисовки для ресурсов графического конвейера.)

Надеюсь, меня не проголосуют, я все еще изучаю dx12, поэтому могу ошибаться, извините.

Очень хороший ответ, особенно от человека, который все еще изучает D3D12. Я полностью поддерживаю предложение просто использовать одну кучу дескрипторов, поскольку изменение кучи дескрипторов является дорогостоящим, и вы также избегаете хлопот, связанных с дублированием ресурсов, копированием дескрипторов и т. д. (что, я не думаю, будет работать, потому что это предназначено только для копирования дескрипторов из не -shader видимые дескрипторные кучи в кучи, видимые шейдером).

Maico De Blasio 24.05.2024 16:40

Другие вопросы по теме