Archived
1
Fork 0

Add offscreen rendering

This commit is contained in:
Joshua Goins 2018-10-17 09:28:47 -04:00
parent 3f96161dff
commit b5dcebe55e
4 changed files with 168 additions and 47 deletions

View file

@ -9,11 +9,16 @@ struct RenderTarget {
VkSwapchainKHR swapchain = nullptr;
VkExtent2D extent = {};
uint32_t numImages = 0;
uint32_t numImages = 0, currentImage = 0;
VkImage* images = nullptr;
VkImageView* imageViews = nullptr;
VkFramebuffer* framebuffers = nullptr;
VkImage* swapchainImages = nullptr;
VkImageView* swapchainImageViews = nullptr;
VkFramebuffer* swapchainFramebuffers = nullptr;
VkImage* offscreenImages = nullptr;
VkDeviceMemory* offscreenMemory = nullptr;
VkImageView* offscreenImageViews = nullptr;
VkFramebuffer* offscreenFramebuffers = nullptr;
VkCommandBuffer* commandBuffers = nullptr;

View file

@ -13,9 +13,16 @@ public:
void render(VkCommandBuffer commandBuffer, World& world, RenderTarget* target);
VkRenderPass getRenderPass() const {
return renderPass_;
}
private:
void createRenderPass();
void createPipeline();
VkRenderPass renderPass_ = nullptr;
VkPipelineLayout pipelineLayout_ = nullptr;
VkPipeline pipeline_ = nullptr;

View file

@ -42,13 +42,12 @@ Renderer::~Renderer() {
}
void Renderer::render(World& world, RenderTarget* target) {
uint32_t imageIndex = 0;
vkAcquireNextImageKHR(device_, target->swapchain, UINT64_MAX, target->imageAvailableSemaphore, nullptr, &imageIndex);
vkAcquireNextImageKHR(device_, target->swapchain, UINT64_MAX, target->imageAvailableSemaphore, nullptr, &target->currentImage);
vkWaitForFences(device_, 1, &target->fences[imageIndex], true, UINT64_MAX);
vkResetFences(device_, 1, &target->fences[imageIndex]);
vkWaitForFences(device_, 1, &target->fences[target->currentImage], true, UINT64_MAX);
vkResetFences(device_, 1, &target->fences[target->currentImage]);
const VkCommandBuffer commandBuffer = target->commandBuffers[imageIndex];
const VkCommandBuffer commandBuffer = target->commandBuffers[target->currentImage];
VkCommandBufferBeginInfo beginInfo = {};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
@ -67,11 +66,13 @@ void Renderer::render(World& world, RenderTarget* target) {
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
worldPass_->render(commandBuffer, world, target);
VkClearValue clearColor = {};
VkRenderPassBeginInfo renderPassBeginInfo = {};
renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassBeginInfo.framebuffer = target->framebuffers[imageIndex];
renderPassBeginInfo.framebuffer = target->swapchainFramebuffers[target->currentImage];
renderPassBeginInfo.renderPass = presentationRenderPass_;
renderPassBeginInfo.renderArea.extent = target->extent;
renderPassBeginInfo.clearValueCount = 1;
@ -79,8 +80,6 @@ void Renderer::render(World& world, RenderTarget* target) {
vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
worldPass_->render(commandBuffer, world, target);
vkCmdEndRenderPass(commandBuffer);
vkEndCommandBuffer(commandBuffer);
@ -97,7 +96,7 @@ void Renderer::render(World& world, RenderTarget* target) {
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = &target->renderFinishedSemaphore;
vkQueueSubmit(graphicsQueue_, 1, &submitInfo, target->fences[imageIndex]);
vkQueueSubmit(graphicsQueue_, 1, &submitInfo, target->fences[target->currentImage]);
VkPresentInfoKHR presentInfo = {};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
@ -105,7 +104,7 @@ void Renderer::render(World& world, RenderTarget* target) {
presentInfo.pWaitSemaphores = &target->renderFinishedSemaphore;
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = &target->swapchain;
presentInfo.pImageIndices = &imageIndex;
presentInfo.pImageIndices = &target->currentImage;
vkQueuePresentKHR(graphicsQueue_, &presentInfo);
}
@ -167,35 +166,101 @@ RenderTarget* Renderer::createSurfaceRenderTarget(VkSurfaceKHR surface, RenderTa
target->numImages = swapchainImageCount;
target->images = new VkImage[swapchainImageCount];
vkGetSwapchainImagesKHR(device_, target->swapchain, &swapchainImageCount, target->images);
target->swapchainImages = new VkImage[swapchainImageCount];
vkGetSwapchainImagesKHR(device_, target->swapchain, &swapchainImageCount, target->swapchainImages);
target->imageViews = new VkImageView[swapchainImageCount];
// create frame resources
target->swapchainImageViews = new VkImageView[swapchainImageCount];
target->swapchainFramebuffers = new VkFramebuffer[swapchainImageCount];
target->offscreenImages = new VkImage[swapchainImageCount];
target->offscreenMemory = new VkDeviceMemory[swapchainImageCount];
target->offscreenImageViews = new VkImageView[swapchainImageCount];
target->offscreenFramebuffers = new VkFramebuffer[swapchainImageCount];
for(uint32_t i = 0; i < swapchainImageCount; i++) {
// swapchain image view
{
VkImageViewCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
createInfo.image = target->images[i];
createInfo.image = target->swapchainImages[i];
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
createInfo.format = VK_FORMAT_B8G8R8A8_SRGB;
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
createInfo.subresourceRange.levelCount = 1;
createInfo.subresourceRange.layerCount = 1;
vkCreateImageView(device_, &createInfo, nullptr, &target->imageViews[i]);
vkCreateImageView(device_, &createInfo, nullptr, &target->swapchainImageViews[i]);
}
target->framebuffers = new VkFramebuffer[swapchainImageCount];
for(uint32_t i = 0; i < swapchainImageCount; i++) {
// swapchain framebuffer
{
VkFramebufferCreateInfo framebufferInfo = {};
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebufferInfo.renderPass = presentationRenderPass_;
framebufferInfo.attachmentCount = 1;
framebufferInfo.pAttachments = &target->imageViews[i];
framebufferInfo.pAttachments = &target->swapchainImageViews[i];
framebufferInfo.width = target->extent.width;
framebufferInfo.height = target->extent.height;
framebufferInfo.layers = 1;
vkCreateFramebuffer(device_, &framebufferInfo, nullptr, &target->framebuffers[i]);
vkCreateFramebuffer(device_, &framebufferInfo, nullptr, &target->swapchainFramebuffers[i]);
}
// offscreen image
{
VkImageCreateInfo imageCreateInfo = {};
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
imageCreateInfo.format = VK_FORMAT_R32G32B32A32_SFLOAT;
imageCreateInfo.extent.width = target->extent.width;
imageCreateInfo.extent.height = target->extent.height;
imageCreateInfo.extent.depth = 1;
imageCreateInfo.mipLevels = 1;
imageCreateInfo.arrayLayers = 1;
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageCreateInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
vkCreateImage(device_, &imageCreateInfo, nullptr, &target->offscreenImages[i]);
VkMemoryRequirements memoryRequirements = {};
vkGetImageMemoryRequirements(device_, target->offscreenImages[i], &memoryRequirements);
VkMemoryAllocateInfo allocateInfo = {};
allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocateInfo.allocationSize = memoryRequirements.size;
allocateInfo.memoryTypeIndex = findMemoryType(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
vkAllocateMemory(device_, &allocateInfo, nullptr, &target->offscreenMemory[i]);
vkBindImageMemory(device_, target->offscreenImages[i], target->offscreenMemory[i], 0);
}
// offscreen image view
{
VkImageViewCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
createInfo.image = target->offscreenImages[i];
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
createInfo.format = VK_FORMAT_R32G32B32A32_SFLOAT;
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
createInfo.subresourceRange.levelCount = 1;
createInfo.subresourceRange.layerCount = 1;
vkCreateImageView(device_, &createInfo, nullptr, &target->offscreenImageViews[i]);
}
// offscreen framebuffer
{
VkFramebufferCreateInfo framebufferInfo = {};
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebufferInfo.renderPass = worldPass_->getRenderPass();
framebufferInfo.attachmentCount = 1;
framebufferInfo.pAttachments = &target->offscreenImageViews[i];
framebufferInfo.width = target->extent.width;
framebufferInfo.height = target->extent.height;
framebufferInfo.layers = 1;
vkCreateFramebuffer(device_, &framebufferInfo, nullptr, &target->offscreenFramebuffers[i]);
}
}
VkCommandBufferAllocateInfo allocateInfo = {};
@ -242,13 +307,13 @@ void Renderer::destroyRenderTarget(RenderTarget* target) {
delete[] target->commandBuffers;
for(uint32_t i = 0; i < target->numImages; i++) {
vkDestroyFramebuffer(device_, target->framebuffers[i], nullptr);
vkDestroyImageView(device_, target->imageViews[i], nullptr);
vkDestroyFramebuffer(device_, target->swapchainFramebuffers[i], nullptr);
vkDestroyImageView(device_, target->swapchainImageViews[i], nullptr);
}
delete[] target->framebuffers;
delete[] target->imageViews;
delete[] target->images;
delete[] target->swapchainFramebuffers;
delete[] target->swapchainImageViews;
delete[] target->swapchainImages;
vkDestroySwapchainKHR(device_, target->swapchain, nullptr);

View file

@ -8,6 +8,7 @@
#include "mesh.h"
WorldPass::WorldPass(Renderer& renderer) : renderer_(renderer) {
createRenderPass();
createPipeline();
}
@ -17,6 +18,18 @@ WorldPass::~WorldPass() {
}
void WorldPass::render(VkCommandBuffer commandBuffer, World& world, RenderTarget* target) {
VkClearValue clearColor = {};
VkRenderPassBeginInfo renderPassBeginInfo = {};
renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassBeginInfo.framebuffer = target->offscreenFramebuffers[target->currentImage];
renderPassBeginInfo.renderPass = renderPass_;
renderPassBeginInfo.renderArea.extent = target->extent;
renderPassBeginInfo.clearValueCount = 1;
renderPassBeginInfo.pClearValues = &clearColor;
vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_);
for(const auto& mesh : world.meshes) {
@ -32,6 +45,37 @@ void WorldPass::render(VkCommandBuffer commandBuffer, World& world, RenderTarget
vkCmdDrawIndexed(commandBuffer, mesh->indices.size(), 1, 0, 0, 0);
}
vkCmdEndRenderPass(commandBuffer);
}
void WorldPass::createRenderPass() {
VkAttachmentDescription colorAttachment = {};
colorAttachment.format = VK_FORMAT_R32G32B32A32_SFLOAT;
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
VkAttachmentReference colorAttachmentRef = {};
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorAttachmentRef;
VkRenderPassCreateInfo renderPassInfo = {};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.attachmentCount = 1;
renderPassInfo.pAttachments = &colorAttachment;
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpass;
vkCreateRenderPass(renderer_.getDevice(), &renderPassInfo, nullptr, &renderPass_);
}
void WorldPass::createPipeline() {
@ -137,7 +181,7 @@ void WorldPass::createPipeline() {
pipelineInfo.pColorBlendState = &colorBlending;
pipelineInfo.pDynamicState = &dynamicState;
pipelineInfo.layout = pipelineLayout_;
pipelineInfo.renderPass = renderer_.getRenderPass();
pipelineInfo.renderPass = renderPass_;
vkCreateGraphicsPipelines(renderer_.getDevice(), nullptr, 1, &pipelineInfo, nullptr, &pipeline_);