Две быстрые заметки, прежде чем мы начнем:
- Код в письменном виде. Я спрашиваю о своем понимании процесса, и если я делаю что-то не так в отношении API Vulkan в целом.
- Код C#, но ответы могут также использовать C ++, я понимать обе версии API - вот почему я не пометил вопрос C#.
Как видно из названия, я использую несколько изображений цепочки обмена, а также несколько изображений в полете и синхронизирую их, используя заборы и семафоры, как вы можете видеть в коде. Однако я не был полностью уверен, куда поместить обновление моего буфера команд и не сериализовать вещи - я все еще не уверен, что то, что я сделал с ним, на самом деле оптимально. Итак, без лишних слов, это моя функция рисования:
private void DrawFrame()
{
device.WaitForFences(inflightFences[currentFrame], true, ulong.MaxValue);
uint nextImage = swapChain.AcquireNextImage(uint.MaxValue, imageAvailableSemaphores[currentFrame], null);
if (!(imagesInFlight[nextImage] is null))
device.WaitForFences(imagesInFlight[nextImage], true, ulong.MaxValue);
imagesInFlight[nextImage] = inflightFences[currentFrame];
device.ResetFences(inflightFences[currentFrame]);
if (monospaceFont.IsCommandBufferDirty)
{
Enumerable.Range(0, swapChainImageCommandBuffers.Length).ForEach(idx => swapChainImageCommandBuffersDirty[idx] = true);
monospaceFont.IsCommandBufferDirty = false;
}
monospaceFont.UpdateBuffer();
if (swapChainImageCommandBuffersDirty[(int)nextImage])
{
var commandBuffer = swapChainImageCommandBuffers[nextImage];
commandBuffer.Begin(CommandBufferUsageFlags.SimultaneousUse);
commandBuffer.BeginRenderPass(renderPass, swapChainFramebuffers[nextImage], new Rect2D(extent), new ClearValue(), SubpassContents.Inline);
monospaceFont.Draw(commandBuffer, (int)nextImage);
commandBuffer.EndRenderPass();
commandBuffer.End();
swapChainImageCommandBuffersDirty[(int)nextImage] = false;
}
graphicsQueue.Submit(
new SubmitInfo
{
CommandBuffers = new[] { swapChainImageCommandBuffers[nextImage] },
SignalSemaphores = new[] { renderingFinishedSemaphores[currentFrame] },
WaitDestinationStageMask = new[] { PipelineStageFlags.ColorAttachmentOutput },
WaitSemaphores = new[] { imageAvailableSemaphores[currentFrame] }
},
inflightFences[currentFrame]);
presentQueue.Present(renderingFinishedSemaphores[currentFrame], swapChain, nextImage);
currentFrame = (currentFrame + 1) % swapChainImages.Length;
}
monospaceFont.UpdateBuffer
копирует новую информацию о вершинах в промежуточный (хост когерентный и видимый) буфер (с Map
/ Unmap
), затем создает временный буфер команд, который вызывает CmdCopyBuffer
для копирования данных из промежуточного буфера в конечный (вершинный) буфер.
monospaceFont.Draw
связывает конвейер, буфер вершин и дескрипторы шейдеров, затем вызывает Draw
.
Я не получаю предупреждений или ошибок слоя отладки, и все работает со скоростью ~ 9k fps (так что я не думаю, что я испортил конвейеры слишком плохо), без сбоев и странных артефактов на экране , но мой лог c правильный?