Вот неисчерпывающий список Vulkan и DirectX 12. Он составлен с использованием критериев, аналогичных критериям Натана.
В целом оба API удивительно похожи. Такие вещи, как этапы шейдера, остаются неизменными по сравнению с DX11 и OpenGL. И, очевидно, DirectX использует представления, чтобы сделать вещи видимыми для шейдеров. Vulkan также использует представления, но они встречаются реже.
Поведение видимости шейдера немного отличается между ними. Vulkan использует маску, чтобы определить, видим ли дескриптор на различных этапах шейдера. DX12 справляется с этим немного по-другому, видимость ресурсов выполняется либо на одном этапе, либо на всех этапах.
Я сломал набор параметров дескриптора / корневого параметра как мог. Обработка дескрипторов - одна из областей, которые сильно различаются между двумя API. Тем не менее, конечный результат довольно похож.
Основы API
Vulkan DirectX 12
--------------- ---------------
n/a IDXGIFactory4
VkInstance n/a
VkPhysicalDevice IDXGIAdapter1
VkDevice ID3D12Device
VkQueue ID3D12CommandQueue
VkSwapchain IDXGISwapChain3
VkFormat DXGI_FORMAT
SPIR-V D3D12_SHADER_BYTECODE
VkFence fences
VkSemaphore n/a
VkEvent n/a
Слой Vulkan WSI предоставляет изображения для цепочки обмена. DX12 требует создания ресурсов для представления изображения.
Общее поведение очереди довольно похоже между ними. При отправке из нескольких потоков есть некоторая особенность.
Постараюсь обновить, как я помню больше вещей ...
Командный буфер и пул
Vulkan DirectX 12
--------------- ---------------
VkCommandPool ID3D12CommandAllocator
VkCommandBuffer ID3D12CommandList/ID3D12GraphicsCommandList
В словах о пуле команд / распределителе из документов Vulkan / DX12 поведение описывается совершенно другими словами, но фактическое поведение довольно похоже. Пользователи могут свободно выделять много буферов / списков команд из пула. Однако, только один буфер / список команд из пула может быть записан. Пулы не могут быть разделены между потоками. Таким образом, несколько потоков требуют нескольких пулов. Вы также можете начать запись сразу после отправки буфера / списка команд на обоих.
Список команд DX12 создается в открытом состоянии. Я нахожу это немного раздражающим, так как я привык к Вулкану. DX12 также требует и явного сброса распределителя команд и списка команд. Это необязательное поведение в Vulkan.
Дескрипторы
Vulkan DirectX 12
--------------- ---------------
VkDescriptorPool n/a
VkDescriptorSet n/a
VkDescriptorSetLayout n/a
VkDescriptorSetLayoutBinding RootParameter**
n/a ID3D12DescriptorHeap
** RootParameter - не точный эквивалент VkDescriptorSetLayoutBinding, но похожее мышление в более широкой картине.
VkDescriptorPool и ID3D12DescriptorHeaps в некотором роде похожи (спасибо Николасу) в том, что они оба управляют распределением самих дескрипторов.
Следует отметить, что DX12 поддерживает не более двух куч дескрипторов, привязанных к списку команд в любой момент времени. Один CBVSRVUAV и один сэмплер. Вы можете иметь столько таблиц дескрипторов, сколько захотите, ссылаясь на эти кучи.
На стороне Vulkan существует жесткое ограничение на максимальное количество наборов дескрипторов, которые вы сообщаете пулу дескрипторов. В обоих случаях вам придется немного учесть количество дескрипторов для каждого типа, который может иметь пул / куча. Вулкан также более явный с типом дескрипторов. Принимая во внимание, что дескрипторы DX12 являются либо CBVSRVUAV, либо сэмплером.
DX12 также имеет функцию, с помощью которой вы можете сортировать CBV на лету, используя SetGraphicsRootConstantBufferView. Однако SRV-версия этого SetGraphicsRootShaderResourceView не работает с текстурами. Это в документации - но вам может понадобиться пара часов, чтобы понять это, если вы не внимательный читатель.
Трубопровод
Vulkan DirectX 12
--------------- ---------------
VkPipelineLayout RootSignature***
VkPipeline ID3D12PipelineState
VkVertexInputAttributeDescription D3D12_INPUT_ELEMENT_DESC
VkVertexInputBindingDescription "
* ** RootSignature - не точный эквивалент VkPipelineLayout .
DX12 объединяет атрибут вершины и привязку в одном описании.
Изображения и буферы
Vulkan DirectX 12
--------------- ---------------
VkImage ID3D12Resource
VkBuffer ID3D12Resource
uniform buffer constant buffer
index buffer index buffer
vertex buffer vertex buffer
VkSampler sampler
barriers/transitions barriers/transitions
Барьеры на обоих API ломаются немного по-разному, но имеют одинаковый чистый результат.
RenderPasses / RenderTargets
Vulkan DirectX 12
--------------- ---------------
VkRenderPass render pass
VkFramebuffer collection of ID3D12Resource
subpass n/a
n/a render target
У проходов рендеринга Vulkan есть хорошая функция автоматического разрешения. DX12 не имеет этого AFIAK. Оба API предоставляют функции для ручного разрешения.
Нет прямой эквивалентности между VkFramebuffer и любыми объектами в DX12. Коллекция ID3D12Resource, которая отображается на RTVs, является довольно схожей.
VkFramebuffer действует более или менее как пул вложений, на который VkRenderPass ссылается с помощью индекса. Подпроходы в VkRenderPass могут ссылаться на любое из вложений в VkFramebuffer, предполагая, что одно и то же вложение не упоминается более одного раза за подпроход. Максимальное количество используемых цветовых вложений ограничено значением VkPhysicalDeviceLimits.maxColorAttachments.
Цели рендеринга DX12 - это просто RTV, которые поддерживаются объектами ID3D12Resource. Максимальное количество одновременно используемых цветовых вложений ограничено D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT (8).
Оба API требуют указания целей / проходов рендеринга при создании объектов конвейера. Тем не менее, Vulkan позволяет вам использовать совместимые проходы рендеринга, поэтому вы не привязаны к тем, которые вы указали при создании трубопровода. Я не тестировал его на DX12, но, думаю, поскольку это просто RTV, то же самое относится и к DX12.