src/ngfx/porting/vulkan/VKGraphics.cpp

Functions

Name
void bindBufferFN0(CommandBuffer * commandBuffer, Buffer * buffer, uint32_t set, Pipeline * currentPipeline, const VkDescriptorSet * descriptorSet)

Functions Documentation

function bindBufferFN0

static void bindBufferFN0(
    CommandBuffer * commandBuffer,
    Buffer * buffer,
    uint32_t set,
    Pipeline * currentPipeline,
    const VkDescriptorSet * descriptorSet
)

Source code

/*
 * Copyright 2020 GoPro Inc.
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
#include "ngfx/porting/vulkan/VKGraphics.h"
#include "ngfx/porting/vulkan/VKBuffer.h"
#include "ngfx/porting/vulkan/VKComputePipeline.h"
#include "ngfx/porting/vulkan/VKConfig.h"
#include "ngfx/porting/vulkan/VKDebugUtil.h"
#include "ngfx/porting/vulkan/VKGraphicsContext.h"
#include "ngfx/porting/vulkan/VKGraphicsPipeline.h"
#include "ngfx/porting/vulkan/VKRenderPass.h"
#include "ngfx/porting/vulkan/VKTexture.h"
using namespace ngfx;

void VKGraphics::beginRenderPass(CommandBuffer *commandBuffer,
                                 RenderPass *renderPass,
                                 Framebuffer *framebuffer, glm::vec4 clearColor,
                                 float clearDepth, uint32_t clearStencil) {
  currentRenderPass = renderPass;
  currentFramebuffer = framebuffer;
  auto &vkCommandBuffer = vk(commandBuffer)->v;
  auto vkFramebuffer = vk(framebuffer);
  auto &vkAttachmentInfos = vkFramebuffer->vkAttachmentInfos;
  std::vector<VkClearValue> clearValues(vkAttachmentInfos.size());
  for (uint32_t j = 0; j < vkAttachmentInfos.size(); j++) {
    auto &info = vkAttachmentInfos[j];
    bool depthStencilAttachment =
        info.imageUsageFlags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
    if (depthStencilAttachment)
      clearValues[j].depthStencil = {clearDepth, clearStencil};
    else
      clearValues[j].color = {
          {clearColor[0], clearColor[1], clearColor[2], clearColor[3]}};
  }
  VkRenderPassBeginInfo renderPassBeginInfo = {
      VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
      nullptr,
      vk(renderPass)->v,
      vk(framebuffer)->v,
      {{0, 0}, {vk(framebuffer)->w, vk(framebuffer)->h}},
      uint32_t(clearValues.size()),
      clearValues.data()};
  VK_TRACE(vkCmdBeginRenderPass(vkCommandBuffer, &renderPassBeginInfo,
                                VK_SUBPASS_CONTENTS_INLINE));

  auto vkRenderPass = vk(renderPass);
  for (uint32_t j = 0; j < framebuffer->attachments.size(); j++) {
    auto &attachment = framebuffer->attachments[j];
    auto vkTexture = (VKTexture *)attachment.texture;
    uint32_t baseIndex =
        attachment.layer * vkTexture->vkImage.createInfo.mipLevels +
        attachment.level;
    vkTexture->vkImage.imageLayout[baseIndex] =
        vkRenderPass->createInfo.pAttachments[j].initialLayout;
  }
}

void VKGraphics::endRenderPass(CommandBuffer *commandBuffer) {
  VK_TRACE(vkCmdEndRenderPass(vk(commandBuffer)->v));

  auto vkRenderPass = vk(currentRenderPass);
  auto framebuffer = currentFramebuffer;
  for (uint32_t j = 0; j < framebuffer->attachments.size(); j++) {
    auto &attachment = framebuffer->attachments[j];
    auto vkTexture = (VKTexture *)attachment.texture;
    uint32_t baseIndex =
        attachment.layer * vkTexture->vkImage.createInfo.mipLevels +
        attachment.level;
    vkTexture->vkImage.imageLayout[baseIndex] =
        vkRenderPass->createInfo.pAttachments[j].finalLayout;
  }

  currentRenderPass = nullptr;
}

void VKGraphics::bindComputePipeline(CommandBuffer *commandBuffer,
                                     ComputePipeline *computePipeline) {
  VK_TRACE(vkCmdBindPipeline(vk(commandBuffer)->v,
                             VK_PIPELINE_BIND_POINT_COMPUTE,
                             vk(computePipeline)->v));
  currentPipeline = computePipeline;
}

void VKGraphics::bindGraphicsPipeline(CommandBuffer *commandBuffer,
                                      GraphicsPipeline *graphicsPipeline) {
  VK_TRACE(vkCmdBindPipeline(vk(commandBuffer)->v,
                             VK_PIPELINE_BIND_POINT_GRAPHICS,
                             vk(graphicsPipeline)->v));
  currentPipeline = graphicsPipeline;
}

void VKGraphics::bindTexture(CommandBuffer *commandBuffer, Texture *texture,
                             uint32_t set) {
  auto vkTexture = vk(texture);
  VkPipelineLayout pipelineLayout;
  VkPipelineBindPoint pipelineBindPoint;
  VkDescriptorSet *descriptorSet = nullptr;
  if (VKGraphicsPipeline *graphicsPipeline =
          dynamic_cast<VKGraphicsPipeline *>(currentPipeline)) {
    if (!(vkTexture->imageUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT)) {
      NGFX_ERR("incorrect image usage flags: missing IMAGE_USAGE_SAMPLED_BIT");
    }
    pipelineLayout = graphicsPipeline->pipelineLayout;
    pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
    descriptorSet = &vkTexture->samplerDescriptorSet;
  } else if (VKComputePipeline *computePipeline =
                 dynamic_cast<VKComputePipeline *>(currentPipeline)) {
    if (!(vkTexture->imageUsageFlags & VK_IMAGE_USAGE_STORAGE_BIT)) {
      NGFX_ERR("incorrect image usage flags: missing IMAGE_USAGE_STORAGE_BIT");
    }
    pipelineLayout = computePipeline->pipelineLayout;
    pipelineBindPoint = VK_PIPELINE_BIND_POINT_COMPUTE;
    descriptorSet = &vkTexture->storageImageDescriptorSet;
  } else
    NGFX_ERR();
  VK_TRACE(vkCmdBindDescriptorSets(vk(commandBuffer)->v, pipelineBindPoint,
                                   pipelineLayout, set, 1, descriptorSet, 0,
                                   nullptr));
}

void VKGraphics::bindVertexBuffer(CommandBuffer *commandBuffer, Buffer *buffer,
                                  uint32_t location, uint32_t stride) {
  VkDeviceSize offsets[] = {0};
  VK_TRACE(vkCmdBindVertexBuffers(vk(commandBuffer)->v, location, 1,
                                  &vk(buffer)->v, offsets));
}
void VKGraphics::bindIndexBuffer(CommandBuffer *commandBuffer, Buffer *buffer,
                                 IndexFormat indexFormat) {
  VkDeviceSize offset = 0;
  VK_TRACE(vkCmdBindIndexBuffer(vk(commandBuffer)->v, vk(buffer)->v, offset,
                                VkIndexType(indexFormat)));
}
static void bindBufferFN0(CommandBuffer *commandBuffer, Buffer *buffer,
                          uint32_t set, Pipeline *currentPipeline,
                          const VkDescriptorSet *descriptorSet) {
  VkPipelineLayout pipelineLayout;
  VkPipelineBindPoint pipelineBindPoint;
  if (VKGraphicsPipeline *graphicsPipeline =
          dynamic_cast<VKGraphicsPipeline *>(currentPipeline)) {
    pipelineLayout = graphicsPipeline->pipelineLayout;
    pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
  } else if (VKComputePipeline *computePipeline =
                 dynamic_cast<VKComputePipeline *>(currentPipeline)) {
    pipelineLayout = computePipeline->pipelineLayout;
    pipelineBindPoint = VK_PIPELINE_BIND_POINT_COMPUTE;
  } else
    NGFX_ERR();
  VK_TRACE(vkCmdBindDescriptorSets(vk(commandBuffer)->v, pipelineBindPoint,
                                   pipelineLayout, set, 1, descriptorSet, 0,
                                   nullptr));
}

void VKGraphics::bindUniformBuffer(CommandBuffer *commandBuffer, Buffer *buffer,
                                   uint32_t set,
                                   ShaderStageFlags shaderStageFlags) {
  bindBufferFN0(commandBuffer, buffer, set, currentPipeline,
                &vk(buffer)->getUboDescriptorSet(shaderStageFlags));
}

void VKGraphics::bindStorageBuffer(CommandBuffer *commandBuffer, Buffer *buffer,
                                   uint32_t set,
                                   ShaderStageFlags shaderStageFlags) {
  bindBufferFN0(commandBuffer, buffer, set, currentPipeline,
                &vk(buffer)->getSsboDescriptorSet(shaderStageFlags));
}

void VKGraphics::dispatch(CommandBuffer *commandBuffer, uint32_t groupCountX,
                          uint32_t groupCountY, uint32_t groupCountZ,
                          uint32_t threadsPerGroupX, uint32_t threadsPerGroupY,
                          uint32_t threadsPerGroupZ) {
  VK_TRACE(vkCmdDispatch(vk(commandBuffer)->v, groupCountX, groupCountY,
                         groupCountZ));
}

void VKGraphics::draw(CommandBuffer *commandBuffer, uint32_t vertexCount,
                      uint32_t instanceCount, uint32_t firstVertex,
                      uint32_t firstInstance) {
  VK_TRACE(vkCmdDraw(vk(commandBuffer)->v, vertexCount, instanceCount,
                     firstVertex, firstInstance));
}
void VKGraphics::drawIndexed(CommandBuffer *cmdBuffer, uint32_t indexCount,
                             uint32_t instanceCount, uint32_t firstIndex,
                             int32_t vertexOffset, uint32_t firstInstance) {
  VK_TRACE(vkCmdDrawIndexed(vk(cmdBuffer)->v, indexCount, instanceCount,
                            firstIndex, vertexOffset, firstInstance));
}

void VKGraphics::setViewport(CommandBuffer *commandBuffer, Rect2D r) {
  viewport = r;
  VkViewport vkViewport = {float(r.x), float(r.y), float(r.w),
                           float(r.h), 0.0f,       1.0f};
  VK_TRACE(vkCmdSetViewport(vk(commandBuffer)->v, 0, 1, &vkViewport));
}
void VKGraphics::setScissor(CommandBuffer *commandBuffer, Rect2D r) {
  scissorRect = r;
#ifdef ORIGIN_BOTTOM_LEFT
  auto &v = viewport;
  VkRect2D vkScissorRect = {{r.x, int32_t(v.h) - r.y - int32_t(r.h)},
                            {r.w, r.h}};
#else
  VkRect2D vkScissorRect = {{r.x, r.y}, {r.w, r.h}};
#endif
  VK_TRACE(vkCmdSetScissor(vk(commandBuffer)->v, 0, 1, &vkScissorRect));
}

void VKGraphics::waitIdle(CommandBuffer *cmdBuffer) {
  vk(ctx)->vkDevice.waitIdle();
}

Graphics *Graphics::create(GraphicsContext *ctx) {
  VKGraphics *vkGraphics = new VKGraphics();
  vkGraphics->ctx = ctx;
  vkGraphics->create();
  return vkGraphics;
}

Updated on 3 April 2021 at 20:21:52 PDT