directx-12 - Как использовать список команд с несколькими кучами дескрипторов?

В настоящее время просматривая примеры микрософтов, можно заметить, что для каждого списка команд используется только одна куча cbv_srv_uav (+ возможно, в дополнительной куче сэмплера).

Можно ли использовать несколько куч для одного CommandList?

Итак, я настраиваю кучу и диапазоны

this->mRSVHeap = new urd::DescriptorHeap(
    *this->mDevice,
    urd::DescriptorHeapType::CBV_SRV_UAV,
    1, // shader visible
    2); // space for 2 descriptors (2 textures)

this->mConstHeap = new urd::DescriptorHeap(
    *this->mDevice,
    urd::DescriptorHeapType::CBV_SRV_UAV,
    1, // shader visible
    1); // space for 1 descriptor

urd::DescriptorRange ranges[3];
ranges[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 2, 0); // first and second descriptor in rsv heap (t0, t1)
ranges[1].Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0); // first descriptor in cbv heap (b0)
ranges[2].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 2); // same texture used as first range (again first descriptor in rsv, accessable by t2)

после этого я определяю таблицы дескрипторов

rootParam[0].InitDescTable(1, &ranges[0], D3D12_SHADER_VISIBILITY_PIXEL);
rootParam[1].InitDescTable(1, &ranges[1], D3D12_SHADER_VISIBILITY_ALL);
rootParam[2].InitDescTable(1, &ranges[2], D3D12_SHADER_VISIBILITY_PIXEL);

Итак, я создаю shaderResourceViews для текстуры 1 и 2 со смещением процессора 0 и 1 в куче rsv и constantbufferview для постоянного буфера со смещением процессора 0 в куче cbv.

нравится:

D3D12_CPU_DESCRIPTOR_HANDLE handle = this->ConstHeap->GetCPUDescriptorHandleForHeapStart();
handle.ptr += index * SIZE_OF_ONE_DESCRIPTOR_CBV_SRV_UAV_TYPE;
CreateConstantBufferView(&desc, handle)

теперь пришло время указать списку команд ссылаться на эти кучи

ID3D12DescriptorHeap* ppHeaps[] = { this->mRSVHeap.Get(), this->mConstHeap.Get() };
this->mCommandList->GetRef()->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);

после этого всегда выкидывает закрытие списка команд.

ThrowIfFailed(this->mCommandList->Close());

Вот как я сообщаю списку команд, какая куча для какой таблицы:

this->mCommandList->GetRef()->SetGraphicsRootDescriptorTable(0, this->mRSVHeap->GetGPUHeapAddressAtOffset(0));
this->mCommandList->GetRef()->SetGraphicsRootDescriptorTable(1, this->mConstHeap->GetGPUHeapAddressAtOffset(0));
this->mCommandList->GetRef()->SetGraphicsRootDescriptorTable(2, this->mRSVHeap->GetGPUHeapAddressAtOffset(0));

Он отлично работает, если я описываю все объекты в одной куче дескрипторов (как в примерах) и просто использую разные смещения этой кучи.

Вывод отладки:

D3D12 ОШИБКА: ID3D12CommandList :: SetDescriptorHeaps: pDescriptorHeaps [1] устанавливает тип кучи дескриптора, который появляется ранее в массиве pDescriptorHeaps. Одновременно может быть установлен только один из любого заданного типа кучи дескриптора. [ОШИБКА ВЫПОЛНЕНИЯ № 554: SET_DESCRIPTOR_HEAP_INVALID] D3D12 ОШИБКА: CCommandList :: SetGraphicsRootDescriptorTable: куча дескрипторов CBV_SRV_UAV в настоящее время не установлена ​​в списке команд, поэтому установка таблицы корневых дескрипторов для CBV_SRV_U недопустима. [ОШИБКА ВЫПОЛНЕНИЯ № 708: SET_DESCRIPTOR_TABLE_INVALID] D3D12 ОШИБКА: CCommandList :: SetGraphicsRootDescriptorTable: куча дескриптора CBV_SRV_UAV в настоящее время не установлена ​​в списке команд, поэтому установка таблицы корневого дескриптора для CBV_SRV_UAV недопустима. [ОШИБКА ВЫПОЛНЕНИЯ № 708: SET_DESCRIPTOR_TABLE_INVALID] D3D12 ОШИБКА: CCommandList :: SetGraphicsRootDescriptorTable: куча дескриптора CBV_SRV_UAV в настоящее время не установлена ​​в списке команд, поэтому установка таблицы корневого дескриптора для CBV_SRV_UAV недопустима. [ОШИБКА ВЫПОЛНЕНИЯ № 708: SET_DESCRIPTOR_TABLE_INVALID]


person Raphael Mayer    schedule 20.08.2015    source источник
comment
Включили ли вы уровень отладки, чтобы получить удобочитаемую ошибку из-за того, что вы сделали неправильно? Поищите в примерах ссылки на «D3D12GetDebugInterface».   -  person Adam Miles    schedule 20.08.2015
comment
да, я сделал, обновил op с выводом отладки. Кажется, это ответ на мой вопрос. !! Только один из любого типа кучи дескриптора может быть установлен одновременно. !!   -  person Raphael Mayer    schedule 20.08.2015
comment
Только одна из любой заданной кучи может быть установлена ​​одновременно, да, но не во всем списке команд. Вы можете изменять кучи в списке команд, а не несколько куч CBV / SRV / UAV (или куч сэмплера) в одном вызове.   -  person Adam Miles    schedule 20.08.2015
comment
Спасибо за разъяснения.   -  person Raphael Mayer    schedule 21.08.2015
comment
возможно, вам стоит опубликовать ответ и получить заслуженные баллы.   -  person Raphael Mayer    schedule 21.08.2015


Ответы (1)


Ограничение состоит в том, что одновременно может быть установлена ​​только одна куча каждого типа (CBV / SRV / UAV и Samplers). Таким образом, одновременно могут быть установлены только две кучи дескрипторов.

Однако важно отметить, что набор кучи дескрипторов может изменяться во время списка команд.

person Adam Miles    schedule 21.08.2015
comment
Не рекомендуется изменять кучи дескрипторов внутри списка команд, так как это может сильно снизить производительность на некотором оборудовании. Правильный способ - выделить большую кучу и по запросу скопировать в нее дескрипторы из кучи, не видимой шейдером. - person galop1n; 26.01.2016