Обновление (вершинных) буферов и командных буферов в Vulkan с несколькими изображениями в полете - PullRequest
0 голосов
/ 03 мая 2020

Две быстрые заметки, прежде чем мы начнем:

  1. Код в письменном виде. Я спрашиваю о своем понимании процесса, и если я делаю что-то не так в отношении API Vulkan в целом.
  2. Код 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 правильный?

...