src/ngfx/porting/vulkan/VKGraphicsContext.cpp
Defines
Name | |
---|---|
MAX_DESCRIPTOR_SETS | |
MAX_DESCRIPTORS |
Macro Documentation
define MAX_DESCRIPTOR_SETS
#define MAX_DESCRIPTOR_SETS MAX_DESCRIPTORS * 4
define MAX_DESCRIPTORS
#define MAX_DESCRIPTORS 1024
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/VKGraphicsContext.h"
using namespace ngfx;
using namespace std;
#define MAX_DESCRIPTOR_SETS MAX_DESCRIPTORS * 4
#define MAX_DESCRIPTORS 1024
void VKGraphicsContext::create(const char *appName, bool enableDepthStencil,
bool debug) {
this->debug = debug;
vkInstance.create(appName, "Graphics Abstraction Engine", 0, debug);
auto instance = vkInstance.v;
if (debug)
VKDebugMessenger::inst.create(instance);
vkPhysicalDevice.create(instance);
vkDevice.create(&vkPhysicalDevice);
vkCommandPool.create(vkDevice.v, vkDevice.queueFamilyIndices.graphics);
vkQueue.create(this, vkDevice.queueFamilyIndices.graphics, 0);
initDescriptorPool();
vkDescriptorSetLayoutCache.create(vkDevice.v);
this->enableDepthStencil = enableDepthStencil;
depthFormat = PixelFormat(vkPhysicalDevice.depthFormat);
}
VKGraphicsContext::~VKGraphicsContext() {
VK_TRACE(vkDestroyDescriptorPool(vkDevice.v, vkDescriptorPool, nullptr));
if (debug)
VKDebugMessenger::inst.destroy();
}
void VKGraphicsContext::initDescriptorPool() {
VkResult vkResult;
descriptorPoolSizes = {
{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, MAX_DESCRIPTORS},
{VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, MAX_DESCRIPTORS},
{VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, MAX_DESCRIPTORS},
{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, MAX_DESCRIPTORS}};
descriptorPoolCreateInfo = {VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
nullptr,
0,
MAX_DESCRIPTOR_SETS,
uint32_t(descriptorPoolSizes.size()),
descriptorPoolSizes.data()};
V(vkCreateDescriptorPool(vkDevice.v, &descriptorPoolCreateInfo, nullptr,
&vkDescriptorPool));
};
RenderPass *VKGraphicsContext::getRenderPass(RenderPassConfig config) {
for (auto &r : vkRenderPassCache) {
if (r->config == config)
return &r->vkRenderPass;
}
auto renderPassData = make_unique<VKRenderPassData>();
initRenderPass(config, renderPassData->vkRenderPass);
auto result = &renderPassData->vkRenderPass;
vkRenderPassCache.emplace_back(std::move(renderPassData));
return result;
}
void VKGraphicsContext::initRenderPass(const RenderPassConfig &config,
VKRenderPass &renderPass) {
std::vector<VkAttachmentDescription> attachments;
uint32_t depthAttachmentBaseIndex = 0;
for (uint32_t j = 0; j < config.numColorAttachments(); j++) {
auto &colorAttachmentDesc = config.colorAttachmentDescriptions[j];
VkFormat colorFormat = VkFormat(colorAttachmentDesc.format);
VkImageLayout initialLayout =
(colorAttachmentDesc.initialLayout)
? VkImageLayout(*colorAttachmentDesc.initialLayout)
: VK_IMAGE_LAYOUT_UNDEFINED;
VkImageLayout finalLayout =
(colorAttachmentDesc.finalLayout)
? VkImageLayout(*colorAttachmentDesc.finalLayout)
: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
attachments.push_back(
{0, colorFormat, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_CLEAR,
VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_CLEAR,
VK_ATTACHMENT_STORE_OP_DONT_CARE, initialLayout, finalLayout});
}
auto &depthStencilAttachmentDesc = config.depthStencilAttachmentDescription;
if (depthStencilAttachmentDesc) {
depthAttachmentBaseIndex = attachments.size();
VkFormat depthFormat = VkFormat(depthStencilAttachmentDesc->format);
VkImageLayout initialLayout =
(depthStencilAttachmentDesc->initialLayout)
? VkImageLayout(*depthStencilAttachmentDesc->initialLayout)
: VK_IMAGE_LAYOUT_UNDEFINED;
VkImageLayout finalLayout =
(depthStencilAttachmentDesc->finalLayout)
? VkImageLayout(*depthStencilAttachmentDesc->finalLayout)
: VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
attachments.push_back(
{0, depthFormat, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_CLEAR,
VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_CLEAR,
VK_ATTACHMENT_STORE_OP_DONT_CARE, initialLayout, finalLayout});
}
std::vector<VkAttachmentReference> colorReferences(
config.numColorAttachments());
for (uint32_t j = 0; j < colorReferences.size(); j++) {
colorReferences[j] = {j, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
}
VkAttachmentReference depthReference = {
depthAttachmentBaseIndex,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL};
std::vector<VkSubpassDescription> subpasses = {
{0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr,
uint32_t(colorReferences.size()), colorReferences.data(), nullptr,
config.depthStencilAttachmentDescription ? &depthReference : nullptr, 0,
nullptr}};
// Subpass dependencies for layout transitions
std::vector<VkSubpassDependency> dependencies = {
{VK_SUBPASS_EXTERNAL, 0, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_MEMORY_READ_BIT,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_DEPENDENCY_BY_REGION_BIT},
{0, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_ACCESS_MEMORY_READ_BIT, VK_DEPENDENCY_BY_REGION_BIT}};
renderPass.create(vkDevice.v, attachments, subpasses, dependencies);
}
#if 0
void VKGraphicsContext::initRenderPassMSAA(const RenderPassConfig &config, VKRenderPass& renderPass) {
std::vector<VkAttachmentDescription> attachments;
uint32_t depthAttachmentBaseIndex = 0;
for (uint32_t j = 0; j<config.numColorAttachments(); j++) {
auto &colorAttachmentDesc = config.colorAttachmentDescriptions[j];
VkFormat colorFormat = VkFormat(colorAttachmentDesc.format);
attachments.push_back({
0, colorFormat, VkSampleCountFlagBits(config.numSamples),
VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
});
attachments.push_back({
0, colorFormat, VkSampleCountFlagBits(1),
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
});
}
if (config.depthStencilAttachmentDescription) {
depthAttachmentBaseIndex = attachments.size();
VkFormat depthFormat = VkFormat(config.depthStencilAttachmentDescription->format);
attachments.push_back({
0, depthFormat, VkSampleCountFlagBits(config.numSamples),
VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
});
if (config.enableDepthStencilResolve) {
attachments.push_back({
0, depthFormat, VkSampleCountFlagBits(1),
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
});
}
}
std::vector<VkAttachmentReference> colorReferences(config.numColorAttachments());
for (uint32_t j = 0; j<colorReferences.size(); j++) {
colorReferences[j] = { 2 * j, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
}
std::vector<VkAttachmentReference> resolveReferences(config.numColorAttachments());
for (uint32_t j = 0; j<resolveReferences.size(); j++) {
resolveReferences[j] = { 2 * j + 1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
}
VkAttachmentReference depthReference = { depthAttachmentBaseIndex, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL };
std::vector<VkSubpassDescription> subpasses = {
{
0, VK_PIPELINE_BIND_POINT_GRAPHICS,
0, nullptr,
uint32_t(colorReferences.size()), colorReferences.data(),
resolveReferences.data(),
config.depthStencilAttachmentDescription ? &depthReference : nullptr,
0, nullptr
}
};
// Subpass dependencies for layout transitions
std::vector<VkSubpassDependency> dependencies = {
{
VK_SUBPASS_EXTERNAL, 0,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_ACCESS_MEMORY_READ_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_DEPENDENCY_BY_REGION_BIT
},
{
0, VK_SUBPASS_EXTERNAL,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_MEMORY_READ_BIT,
VK_DEPENDENCY_BY_REGION_BIT
}
};
renderPass.create(vkDevice.v, attachments, subpasses, dependencies);
}
void VKGraphicsContext::initOffscreenRenderPass(const RenderPassConfig &config, VKRenderPass& renderPass) {
VkFormat colorFormat = VkFormat(defaultOffscreenSurfaceFormat),
depthFormat = vkPhysicalDevice.depthFormat;
std::vector<VkAttachmentDescription> attachments;
uint32_t depthAttachmentBaseIndex = 0;
for (uint32_t j = 0; j<config.numColorAttachments(); j++) {
attachments.push_back({
0, colorFormat, VK_SAMPLE_COUNT_1_BIT,
VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
});
}
if (config.depthStencilAttachmentDescription) {
depthAttachmentBaseIndex = attachments.size();
attachments.push_back({
0, depthFormat, VK_SAMPLE_COUNT_1_BIT,
VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
});
}
std::vector<VkAttachmentReference> colorReferences(config.numColorAttachments());
for (uint32_t j = 0; j<colorReferences.size(); j++) {
colorReferences[j] = { j, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
}
VkAttachmentReference depthReference = {
depthAttachmentBaseIndex, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
};
std::vector<VkSubpassDescription> subpasses = {
{
0, VK_PIPELINE_BIND_POINT_GRAPHICS,
0, nullptr,
uint32_t(colorReferences.size()), colorReferences.data(),
nullptr,
config.depthStencilAttachmentDescription ? &depthReference : nullptr,
0, nullptr
}
};
// Subpass dependencies for layout transitions
std::vector<VkSubpassDependency> dependencies = {
{
VK_SUBPASS_EXTERNAL, 0,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_DEPENDENCY_BY_REGION_BIT
},
{
0, VK_SUBPASS_EXTERNAL,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
VK_DEPENDENCY_BY_REGION_BIT
}
};
renderPass.create(vkDevice.v, attachments, subpasses, dependencies);
}
void VKGraphicsContext::initOffscreenRenderPassMSAA(const RenderPassConfig &config, VKRenderPass& renderPass) {
VkFormat colorFormat = VkFormat(defaultOffscreenSurfaceFormat),
depthFormat = vkPhysicalDevice.depthFormat;
std::vector<VkAttachmentDescription> attachments;
uint32_t depthAttachmentBaseIndex = 0;
for (uint32_t j = 0; j<config.numColorAttachments(); j++) {
attachments.push_back({
0, colorFormat, VkSampleCountFlagBits(config.numSamples),
VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
});
attachments.push_back({
0, colorFormat, VK_SAMPLE_COUNT_1_BIT,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
});
}
if (config.depthStencilAttachmentDescription) {
depthAttachmentBaseIndex = attachments.size();
attachments.push_back({
0, depthFormat, VkSampleCountFlagBits(config.numSamples),
VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
});
if (config.enableDepthStencilResolve) {
attachments.push_back({
0, depthFormat, VK_SAMPLE_COUNT_1_BIT,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
});
}
}
std::vector<VkAttachmentReference> colorReferences(config.numColorAttachments());
for (uint32_t j = 0; j<colorReferences.size(); j++) {
colorReferences[j] = { 2 * j, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
}
std::vector<VkAttachmentReference> resolveReferences(config.numColorAttachments());
for (uint32_t j = 0; j<resolveReferences.size(); j++) {
resolveReferences[j] = { 2 * j + 1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
}
VkAttachmentReference depthReference = { depthAttachmentBaseIndex, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL };
std::vector<VkSubpassDescription> subpasses = {
{
0, VK_PIPELINE_BIND_POINT_GRAPHICS,
0, nullptr,
uint32_t(colorReferences.size()), colorReferences.data(),
resolveReferences.data(),
config.depthStencilAttachmentDescription ? &depthReference : nullptr,
0, nullptr
}
};
// Subpass dependencies for layout transitions
std::vector<VkSubpassDependency> dependencies = {
{
VK_SUBPASS_EXTERNAL, 0,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_DEPENDENCY_BY_REGION_BIT
},
{
0, VK_SUBPASS_EXTERNAL,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
VK_DEPENDENCY_BY_REGION_BIT
}
};
renderPass.create(vkDevice.v, attachments, subpasses, dependencies);
}
#endif
void VKGraphicsContext::createSwapchainFramebuffers(int w, int h) {
// Create frame buffers for every swap chain image
vkSwapchainFramebuffers.resize(vkSwapchain->numImages);
for (uint32_t i = 0; i < vkSwapchainFramebuffers.size(); i++) {
std::vector<VKFramebuffer::VKAttachmentDescriptor> attachments;
if (numSamples != 1)
attachments.push_back({&vkMultisampleColorImageView,
{vkMultisampleColorImage.createInfo.usage}});
attachments.push_back(
{&vkSwapchain->imageViews[i], {VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT}});
if (enableDepthStencil) {
if (numSamples != 1)
attachments.push_back({&vkMultisampleDepthImageView,
{vkMultisampleDepthImage.createInfo.usage}});
attachments.push_back(
{&vkDepthStencilImageView, {vkDepthStencilImage.createInfo.usage}});
}
vkSwapchainFramebuffers[i].create(vkDevice.v, vkDefaultRenderPass->v,
attachments, w, h);
}
}
void VKGraphicsContext::initSemaphores(VkDevice device) {
vkPresentCompleteSemaphore.create(device);
vkRenderCompleteSemaphore.create(device);
}
void VKGraphicsContext::initFences(VkDevice device) {
vkWaitFences.resize(numDrawCommandBuffers);
for (auto &fence : vkWaitFences)
fence.create(device, VK_FENCE_CREATE_SIGNALED_BIT);
vkComputeFence.create(device);
}
void VKGraphicsContext::setSurface(Surface *surface) {
if (surface && !surface->offscreen) {
offscreen = false;
vkSwapchain = make_unique<VKSwapchain>(this, vk(surface));
surfaceFormat = PixelFormat(vkSwapchain->surfaceFormat.format);
numDrawCommandBuffers = vkSwapchain->numImages;
} else {
offscreen = true;
numDrawCommandBuffers = 1;
}
vkDrawCommandBuffers.resize(numDrawCommandBuffers);
for (auto &cmdBuffer : vkDrawCommandBuffers) {
cmdBuffer.create(vkDevice.v, vkCommandPool.v);
}
vkCopyCommandBuffer.create(vkDevice.v, vkCommandPool.v);
vkComputeCommandBuffer.create(vkDevice.v, vkCommandPool.v);
if (surface && numSamples != 1) {
msColorImageCreateInfo = {};
msColorImageCreateInfo.format = VkFormat(surfaceFormat);
msColorImageCreateInfo.extent = {surface->w, surface->h, 1};
msColorImageCreateInfo.samples = VkSampleCountFlagBits(numSamples);
msColorImageCreateInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT;
vkMultisampleColorImage.create(&vkDevice,
msColorImageCreateInfo); // TODO: use
// VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT
// on mobile GPU
vkMultisampleColorImageView.create(vkDevice.v, vkMultisampleColorImage.v,
VK_IMAGE_VIEW_TYPE_2D,
VkFormat(surfaceFormat));
}
if (surface && enableDepthStencil) {
vkDepthStencilImage.create(&vkDevice, {surface->w, surface->h, 1},
vkPhysicalDevice.depthFormat,
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
vkDepthStencilImageView.create(
vkDevice.v, vkDepthStencilImage.v, VK_IMAGE_VIEW_TYPE_2D,
vkPhysicalDevice.depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT);
if (numSamples != 1) {
msDepthImageCreateInfo = {};
msDepthImageCreateInfo.format = vkPhysicalDevice.depthFormat;
msDepthImageCreateInfo.extent = {surface->w, surface->h, 1};
msDepthImageCreateInfo.samples = VkSampleCountFlagBits(numSamples);
msDepthImageCreateInfo.usage =
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT;
vkMultisampleDepthImage.create(&vkDevice,
msDepthImageCreateInfo); // TODO: use
// VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT
// on mobile GPU
vkMultisampleDepthImageView.create(
vkDevice.v, vkMultisampleDepthImage.v, VK_IMAGE_VIEW_TYPE_2D,
vkPhysicalDevice.depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT);
}
}
std::optional<AttachmentDescription> depthAttachmentDescription;
if (enableDepthStencil)
depthAttachmentDescription = {depthFormat};
else
depthAttachmentDescription = nullopt;
if (surface && !surface->offscreen) {
RenderPassConfig onscreenRenderPassConfig = {
{{surfaceFormat, IMAGE_LAYOUT_UNDEFINED, IMAGE_LAYOUT_PRESENT_SRC}},
depthAttachmentDescription,
false,
numSamples};
vkDefaultRenderPass =
(VKRenderPass *)getRenderPass(onscreenRenderPassConfig);
}
defaultOffscreenSurfaceFormat = PixelFormat(VK_FORMAT_R8G8B8A8_UNORM);
RenderPassConfig offscreenRenderPassConfig = {
{{defaultOffscreenSurfaceFormat}},
depthAttachmentDescription,
false,
numSamples};
vkDefaultOffscreenRenderPass =
(VKRenderPass *)getRenderPass(offscreenRenderPassConfig);
vkPipelineCache.create(vkDevice.v);
if (surface && !surface->offscreen)
createSwapchainFramebuffers(surface->w, surface->h);
initSemaphores(vkDevice.v);
initFences(vkDevice.v);
createBindings();
pipelineCache = &vkPipelineCache;
}
CommandBuffer *VKGraphicsContext::drawCommandBuffer(int32_t index) {
if (index == -1)
index = currentImageIndex;
return &vkDrawCommandBuffers[index];
}
CommandBuffer *VKGraphicsContext::copyCommandBuffer() {
return &vkCopyCommandBuffer;
}
CommandBuffer *VKGraphicsContext::computeCommandBuffer() {
return &vkComputeCommandBuffer;
}
void VKGraphicsContext::createBindings() {
device = &vkDevice;
queue = &vkQueue;
defaultRenderPass =
offscreen ? vkDefaultOffscreenRenderPass : vkDefaultRenderPass;
defaultOffscreenRenderPass = vkDefaultOffscreenRenderPass;
swapchain = vkSwapchain.get();
frameFences.resize(vkWaitFences.size());
for (size_t j = 0; j < vkWaitFences.size(); j++)
frameFences[j] = &vkWaitFences[j];
computeFence = &vkComputeFence;
swapchainFramebuffers.resize(vkSwapchainFramebuffers.size());
for (size_t j = 0; j < vkSwapchainFramebuffers.size(); j++)
swapchainFramebuffers[j] = &vkSwapchainFramebuffers[j];
presentCompleteSemaphore = &vkPresentCompleteSemaphore;
renderCompleteSemaphore = &vkRenderCompleteSemaphore;
}
GraphicsContext *GraphicsContext::create(const char *appName,
bool enableDepthStencil, bool debug) {
NGFX_LOG("debug: %s", (debug) ? "true" : "false");
auto vkGraphicsContext = new VKGraphicsContext();
vkGraphicsContext->create(appName, enableDepthStencil, debug);
return vkGraphicsContext;
}
Updated on 3 April 2021 at 20:21:52 PDT