Войти
ПрограммированиеСтатьиГрафика

Vulkan API «Hello Triangle» (3 стр)

Автор:

Пасс вывода

Говорят, что эта часть Vulkan API появилась по инициативе мобильного сектора. Пассы вывода отвечают за состояние кадра и описывают куда и как производить вывод. Нам, пожалуй, понадобится один для дальнейшей работы.

VkResult vkCreateRenderPass(
    VkDevice        device,
    const VkRenderPassCreateInfo*  pCreateInfo,
    const VkAllocationCallbacks*    pAllocator,
    VkRenderPass*      pRenderPass);

typedef struct VkRenderPassCreateInfo {
    VkStructureType      sType;
    const void*        pNext;
    VkRenderPassCreateFlags    flags;
    uint32_t        attachmentCount;
    const VkAttachmentDescription*  pAttachments;
    uint32_t        subpassCount;
    const VkSubpassDescription*    pSubpasses;
    uint32_t        dependencyCount;
    const VkSubpassDependency*  pDependencies;
} VkRenderPassCreateInfo;

Необходимыми для нас полями являются присоединения (attachmentCount/pAttachments) и подпассы (subpassCount/pSubpasses) на которые, в свою очередь, делятся пассы.

Присоединения описывают процесс, происходящий с текстурой во время вывода (операции очистки текстуры, формат, планировку и т.д.):

typedef struct VkAttachmentDescription {
    VkAttachmentDescriptionFlags  flags;
    VkFormat        format;
    VkSampleCountFlagBits    samples;
    VkAttachmentLoadOp    loadOp;
    VkAttachmentStoreOp    storeOp;
    VkAttachmentLoadOp    stencilLoadOp;
    VkAttachmentStoreOp    stencilStoreOp;
    VkImageLayout      initialLayout;
    VkImageLayout      finalLayout;
} VkAttachmentDescription;

Подпассы описывают определенную фазу всего пасса и говорят, что, куда и как писать/читать:

typedef struct VkSubpassDescription {
    VkSubpassDescriptionFlags    flags;
    VkPipelineBindPoint      pipelineBindPoint;
    uint32_t        inputAttachmentCount;
    const VkAttachmentReference*  pInputAttachments;
    uint32_t        colorAttachmentCount;
    const VkAttachmentReference*  pColorAttachments;
    const VkAttachmentReference*  pResolveAttachments;
    const VkAttachmentReference*  pDepthStencilAttachment;
    uint32_t        preserveAttachmentCount;
    const uint32_t*      pPreserveAttachments;
} VkSubpassDescription;

Интересными для нас являются поля для управления точкой привязки – pipelineBindPoint (указывают, используется подпасс графическим конвейером или вычислительным) и присоединениямиcolorAttachmentCount/pColorAttachments. Последние описываются очень лаконичными структурами:

typedef struct VkAttachmentReference {
    uint32_t    attachment;
    VkImageLayout  layout;
} VkAttachmentReference;

которые указывают на слот присоединения и его планировку.

Поскольку пасс вывода не содержит непосредственной информации о текстурах, мы сможем использовать его для вывода в оба изображения цепочки обмена:

VkRenderPass vk_renderPass;
{
  VkAttachmentDescription vk_attachmentDescription;
  {
    vk_attachmentDescription.flags = 0;
    vk_attachmentDescription.format = vk_surfaceFormats[0].format;
    vk_attachmentDescription.samples = VkSampleCountFlagBits::VK_SAMPLE_COUNT_1_BIT;
    vk_attachmentDescription.loadOp = VkAttachmentLoadOp::VK_ATTACHMENT_LOAD_OP_CLEAR;
    vk_attachmentDescription.storeOp = VkAttachmentStoreOp::VK_ATTACHMENT_STORE_OP_STORE;
    vk_attachmentDescription.stencilLoadOp = VkAttachmentLoadOp::VK_ATTACHMENT_LOAD_OP_DONT_CARE;
    vk_attachmentDescription.stencilStoreOp = VkAttachmentStoreOp::VK_ATTACHMENT_STORE_OP_DONT_CARE;
    vk_attachmentDescription.initialLayout = VkImageLayout::VK_IMAGE_LAYOUT_UNDEFINED;
    vk_attachmentDescription.finalLayout = VkImageLayout::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  }

  VkAttachmentReference vk_attachmentReference;
  {
    vk_attachmentReference.attachment = 0;
    vk_attachmentReference.layout = VkImageLayout::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  }
  VkSubpassDescription vk_subpassDescription;
  {
    vk_subpassDescription.flags = 0;
    vk_subpassDescription.pipelineBindPoint = VkPipelineBindPoint::VK_PIPELINE_BIND_POINT_GRAPHICS;
    vk_subpassDescription.inputAttachmentCount = 0;
    vk_subpassDescription.pInputAttachments = nullptr;
    vk_subpassDescription.colorAttachmentCount = 1;
    vk_subpassDescription.pColorAttachments = &vk_attachmentReference;
    vk_subpassDescription.pResolveAttachments = nullptr;
    vk_subpassDescription.pDepthStencilAttachment = nullptr;
    vk_subpassDescription.preserveAttachmentCount = 0;
    vk_subpassDescription.pPreserveAttachments = nullptr;
  }

  VkRenderPassCreateInfo vk_renderPassCreateInfo;
  {
    vk_renderPassCreateInfo.sType = VkStructureType::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
    vk_renderPassCreateInfo.pNext = nullptr;
    vk_renderPassCreateInfo.flags = 0;
    vk_renderPassCreateInfo.attachmentCount = 1;
    vk_renderPassCreateInfo.pAttachments = &vk_attachmentDescription;
    vk_renderPassCreateInfo.subpassCount = 1;
    vk_renderPassCreateInfo.pSubpasses = &vk_subpassDescription;
    vk_renderPassCreateInfo.dependencyCount = 0;
    vk_renderPassCreateInfo.pDependencies = nullptr;
  }
    
  if(vkCreateRenderPass(vk_device, &vk_renderPassCreateInfo, nullptr, &vk_renderPass) != VkResult::VK_SUCCESS)
  {
    throw std::exception("failed to create render pass");
  }
}

Буфер кадра и вид изображения

Вывод графики не производится непосредственно в текстуру, для этого нужен посредник – буфер кадра. С другой стороны, чтение или запись одной и той же текстуры может производится по-разному, а потому есть смысл проводить все операции через объект, описывающий доступ к данным – вид изображения.

План:
•  Для каждого изображения цепочки обмена создать соответствующий вид изображения
•  Для каждого созданного вида изображения создать буфер кадра, рисующий в него

Вид изображения

Вид изображения определяет способ доступа к памяти изображения, т.е. тип, формат, компоненты и мип-уровни.

VkResult vkCreateImageView(
    VkDevice        device,
    const VkImageViewCreateInfo*  pCreateInfo,
    const VkAllocationCallbacks*    pAllocator,
    VkImageView*      pView);

typedef struct VkImageViewCreateInfo {
    VkStructureType    sType;
    const void*      pNext;
    VkImageViewCreateFlags  flags;
    VkImage      image;
    VkImageViewType    viewType;
    VkFormat      format;
    VkComponentMapping  components;
    VkImageSubresourceRange  subresourceRange;
} VkImageViewCreateInfo;

Последний параметр нас не сильно волнует, а вот с помощью format и components мы настроим способ записи в изображение:

typedef struct VkComponentMapping {
    VkComponentSwizzle    r;
    VkComponentSwizzle    g;
    VkComponentSwizzle    b;
    VkComponentSwizzle    a;
} VkComponentMapping;

Структура говорит о том, как читать (или картировать - мапить) каждую компоненту. К примеру, мы можем читать изображение инверсно, если установим поле b значением VkComponentSwizzle::VK_COMPONENT_SWIZZLE_R и т.д.

Буфер кадра

Суть буфера кадра – говорить драйверу, в какие изображения (а точнее в их виды) и с каким пассом производить вывод.

VkResult vkCreateFramebuffer(
    VkDevice        device,
    const VkFramebufferCreateInfo*  pCreateInfo,
    const VkAllocationCallbacks*    pAllocator,
    VkFramebuffer*      pFramebuffer);

typedef struct VkFramebufferCreateInfo {
    VkStructureType    sType;
    const void*      pNext;
    VkFramebufferCreateFlags  flags;
    VkRenderPass    renderPass;
    uint32_t      attachmentCount;
    const VkImageView*    pAttachments;
    uint32_t      width;
    uint32_t      height;
    uint32_t      layers;
} VkFramebufferCreateInfo;

Т.к. нам необходимо производить вывод по очереди в каждое изображение цепочки обмена, необходимо создать по буферу кадра на каждое:

std::vector<VkFramebuffer> vk_framebuffers(vk_swapchainImages.size());
std::vector<VkImageView> vk_imageViews(vk_swapchainImages.size());
{
  for(uint32_t i = 0; i < vk_swapchainImages.size(); ++i)
  {
    auto &vk_imageView = vk_imageViews[i];
    {
      VkImageViewCreateInfo vk_imageViewCreateInfo;
      {
        vk_imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
        vk_imageViewCreateInfo.pNext = nullptr;
        vk_imageViewCreateInfo.flags = 0;
        vk_imageViewCreateInfo.image = vk_swapchainImages[i];
        vk_imageViewCreateInfo.viewType = VkImageViewType::VK_IMAGE_VIEW_TYPE_2D;
        vk_imageViewCreateInfo.format = vk_surfaceFormats[0].format;
        vk_imageViewCreateInfo.components = {
          VkComponentSwizzle::VK_COMPONENT_SWIZZLE_R,
          VkComponentSwizzle::VK_COMPONENT_SWIZZLE_G,
          VkComponentSwizzle::VK_COMPONENT_SWIZZLE_B,
          VkComponentSwizzle::VK_COMPONENT_SWIZZLE_A
        };
        vk_imageViewCreateInfo.subresourceRange;
        {
          vk_imageViewCreateInfo.subresourceRange.aspectMask = VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT;
          vk_imageViewCreateInfo.subresourceRange.baseMipLevel = 0;
          vk_imageViewCreateInfo.subresourceRange.levelCount = 1;
          vk_imageViewCreateInfo.subresourceRange.baseArrayLayer = 0;
          vk_imageViewCreateInfo.subresourceRange.layerCount = 1;
        }
      }

      if(vkCreateImageView(vk_device, &vk_imageViewCreateInfo, nullptr, &vk_imageView) != VkResult::VK_SUCCESS)
      {
        throw std::exception("failed to create image view");
      }
    }

    auto &vk_framebuffer = vk_framebuffers[i];
    {
      VkFramebufferCreateInfo vk_framebufferCreateInfo;
      {
        vk_framebufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
        vk_framebufferCreateInfo.pNext = nullptr;
        vk_framebufferCreateInfo.flags = 0;
        vk_framebufferCreateInfo.renderPass = vk_renderPass;
        vk_framebufferCreateInfo.attachmentCount = 1;
        vk_framebufferCreateInfo.pAttachments = &vk_imageView;
        vk_framebufferCreateInfo.width = vk_surfaceCapabilitiesKHR.currentExtent.width;
        vk_framebufferCreateInfo.height = vk_surfaceCapabilitiesKHR.currentExtent.height;
        vk_framebufferCreateInfo.layers = 1;
      }

      if(vkCreateFramebuffer(vk_device, &vk_framebufferCreateInfo, nullptr, &vk_framebuffer) != VkResult::VK_SUCCESS)
      {
        throw std::exception("failed to create framebuffer");
      }
    }
  }
}
Страницы: 1 2 3 4 5 6 7 Следующая »

#Vulkan, #основы

15 сентября 2016

Комментарии [69]