Moved descriptor pool to renderer
This commit is contained in:
parent
0d205cd7a5
commit
342395129c
@ -9,4 +9,46 @@ namespace gz::vlk {
|
|||||||
vk.destroyBuffer(indexBuffer, indexBufferMemory);
|
vk.destroyBuffer(indexBuffer, indexBufferMemory);
|
||||||
vk.destroyBuffer(vertexBuffer, vertexBufferMemory);
|
vk.destroyBuffer(vertexBuffer, vertexBufferMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Renderer::createDescriptorSetLayoutSampler(uint32_t binding) {
|
||||||
|
// combined image sampler
|
||||||
|
std::vector<vk::DescriptorSetLayoutBinding> sampleFromRenderImageDSLB;
|
||||||
|
sampleFromRenderImageDSLB.emplace_back(vk::DescriptorSetLayoutBinding {
|
||||||
|
.binding = binding,
|
||||||
|
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.stageFlags = vk::ShaderStageFlagBits::eFragment,
|
||||||
|
});
|
||||||
|
vk.createDescriptorSetLayout(sampleFromRenderImageDSLB, sampleFromRenderImageDSL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Renderer::createDescriptorSetSampler() {
|
||||||
|
std::vector<vk::DescriptorSetLayout> layouts2(vk.getScImages().size(), sampleFromRenderImageDSL);
|
||||||
|
vk.createDescriptorSets(layouts2, descriptorPool, sampleFromRenderImageDS);
|
||||||
|
|
||||||
|
assert(renderImageViews.size() == vk.getScImages().size());
|
||||||
|
assert(sampleFromRenderImageDS.size() == vk.getScImages().size());
|
||||||
|
for (size_t i = 0; i < vk.getMaxFramesInFlight(); i++) {
|
||||||
|
vk::DescriptorImageInfo imageI {
|
||||||
|
.sampler = imageSampler,
|
||||||
|
.imageView = renderImageViews[i],
|
||||||
|
.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
||||||
|
};
|
||||||
|
|
||||||
|
vk::WriteDescriptorSet descriptorW{
|
||||||
|
.dstSet = sampleFromRenderImageDS[i],
|
||||||
|
.dstBinding = 0,
|
||||||
|
.dstArrayElement = 0,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
||||||
|
.pImageInfo = &imageI,
|
||||||
|
};
|
||||||
|
// write 1, copy 0
|
||||||
|
vk.getDevice().updateDescriptorSets(descriptorW, nullptr);
|
||||||
|
} // for
|
||||||
|
/* rLog.log0("createDescriptoSetSampler: Created descriptor layout and sets for sampling from renderImages"); */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
// includes for child classes
|
// includes for child classes
|
||||||
#include "vulkan_util.hpp"
|
#include "vulkan_util.hpp"
|
||||||
|
|
||||||
|
#define LOG_SUBLOGS
|
||||||
#include <gz-util/log.hpp>
|
#include <gz-util/log.hpp>
|
||||||
|
|
||||||
#include "texture_manager.hpp"
|
#include "texture_manager.hpp"
|
||||||
@ -42,6 +44,7 @@ namespace gz::vlk {
|
|||||||
* The images are used as render targets, `#ifdef GZ_RENDERER_OWN_RENDER_IMAGES`
|
* The images are used as render targets, `#ifdef GZ_RENDERER_OWN_RENDER_IMAGES`
|
||||||
*
|
*
|
||||||
* After rendering, the current image gets blitted onto the current swap chain image.
|
* After rendering, the current image gets blitted onto the current swap chain image.
|
||||||
|
* These resources need to be created and cleaned up by the subclass
|
||||||
* @todo
|
* @todo
|
||||||
*/
|
*/
|
||||||
/// @{
|
/// @{
|
||||||
@ -51,6 +54,17 @@ namespace gz::vlk {
|
|||||||
vk::Sampler imageSampler;
|
vk::Sampler imageSampler;
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Descriptors
|
||||||
|
* @details
|
||||||
|
* The descriptor pool has to be created by the subclass.
|
||||||
|
*/
|
||||||
|
vk::DescriptorPool descriptorPool;
|
||||||
|
void createDescriptorSetLayoutSampler(uint32_t binding);
|
||||||
|
void createDescriptorSetSampler();
|
||||||
|
vk::DescriptorSetLayout sampleFromRenderImageDSL;
|
||||||
|
std::vector<vk::DescriptorSet> sampleFromRenderImageDS;
|
||||||
|
|
||||||
std::vector<vk::CommandBuffer> commandBuffers;
|
std::vector<vk::CommandBuffer> commandBuffers;
|
||||||
/// On device local memory
|
/// On device local memory
|
||||||
vk::Buffer vertexBuffer;
|
vk::Buffer vertexBuffer;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "renderer2D.hpp"
|
#include "renderer2D.hpp"
|
||||||
|
|
||||||
#include "exceptions.hpp"
|
#include "exceptions.hpp"
|
||||||
|
#include "shape.hpp"
|
||||||
#include "vulkan_allocator.hpp"
|
#include "vulkan_allocator.hpp"
|
||||||
#include "vulkan_instance.hpp"
|
#include "vulkan_instance.hpp"
|
||||||
#include "texture_manager.hpp"
|
#include "texture_manager.hpp"
|
||||||
@ -12,12 +13,32 @@
|
|||||||
#include <vulkan/vulkan_enums.hpp>
|
#include <vulkan/vulkan_enums.hpp>
|
||||||
|
|
||||||
namespace gz::vlk {
|
namespace gz::vlk {
|
||||||
|
#define RENDERER_2D_RENDER_TO_OWN_IMAGES
|
||||||
|
#define RENDERER_2D_COPY_TO_SWAP_CHAIN
|
||||||
|
|
||||||
|
#ifdef RENDERER_2D_RENDER_TO_SWAP_CHAIN
|
||||||
|
#ifdef RENDERER_2D_RENDER_TO_OWN_IMAGES
|
||||||
|
static_assert(false, "RENDERER_2D_RENDER_TO_SWAP_CHAIN and RENDERER_2D_RENDER_TO_OWN_IMAGES defined at the same time");
|
||||||
|
#endif
|
||||||
|
#ifdef RENDERER_2D_COPY_TO_SWAP_CHAIN
|
||||||
|
static_assert(false, "RENDERER_2D_RENDER_TO_SWAP_CHAIN and RENDERER_2D_COPY_TO_SWAP_CHAIN defined at the same time");
|
||||||
|
#endif
|
||||||
|
#ifdef RENDERER_2D_ENABLE_SAMPLE_FROM_RENDER_IMAGES
|
||||||
|
static_assert(false, "RENDERER_2D_RENDER_TO_SWAP_CHAIN and RENDERER_2D_ENABLE_SAMPLE_FROM_RENDER_IMAGES defined at the same time");
|
||||||
|
#endif
|
||||||
|
#elif defined RENDERER_2D_RENDER_TO_OWN_IMAGES
|
||||||
|
/* #ifndef RENDERER_2D_COPY_TO_SWAP_CHAIN */
|
||||||
|
/* #define RENDERER_2D_ENABLE_SAMPLE_FROM_RENDER_IMAGES */
|
||||||
|
/* #endif */
|
||||||
|
#else
|
||||||
|
static_assert(false, "Either RENDERER_2D_RENDER_TO_OWN_IMAGES or RENDERER_2D_RENDER_TO_SWAP_CHAIN must be defined");
|
||||||
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
// INIT & CLEANUP
|
// INIT & CLEANUP
|
||||||
//
|
//
|
||||||
Renderer2D::Renderer2D(VulkanInstance& instance, TextureManager& textureManager) :
|
Renderer2D::Renderer2D(VulkanInstance& instance, TextureManager& textureManager)
|
||||||
Renderer(instance, textureManager)
|
: Renderer(instance, textureManager), shapeBufferManager(instance)
|
||||||
{
|
{
|
||||||
LogCreateInfo logCI {
|
LogCreateInfo logCI {
|
||||||
.logfile = "renderer2D.log",
|
.logfile = "renderer2D.log",
|
||||||
@ -35,10 +56,16 @@ namespace gz::vlk {
|
|||||||
const size_t indexCount = 1000;
|
const size_t indexCount = 1000;
|
||||||
vk.createVertexBuffer<Vertex2D>(vertexCount, vertexBuffer, vertexBufferMemory, vertexBufferSize);
|
vk.createVertexBuffer<Vertex2D>(vertexCount, vertexBuffer, vertexBufferMemory, vertexBufferSize);
|
||||||
vk.createIndexBuffer<uint32_t>(indexCount, indexBuffer, indexBufferMemory, indexBufferSize);
|
vk.createIndexBuffer<uint32_t>(indexCount, indexBuffer, indexBufferMemory, indexBufferSize);
|
||||||
|
#ifdef RENDERER_2D_ENABLE_SAMPLE_FROM_RENDER_IMAGES
|
||||||
|
createDescriptorResources();
|
||||||
|
#endif
|
||||||
initSwapChainDependantResources();
|
initSwapChainDependantResources();
|
||||||
VulkanInstance::registerObjectUsingVulkan("Renderer2D",
|
VulkanInstance::registerObjectUsingVulkan("Renderer2D",
|
||||||
&pipelines[R2Render].pipeline, &renderPass, &vertexBuffer, &vertexBufferMemory.memory, &indexBuffer, &indexBufferMemory.memory,
|
&vertexBuffer, &vertexBufferMemory.memory,
|
||||||
&framebuffers, &renderImages, &renderImageViews, &commandBuffers); // &renderImageMemory,
|
&indexBuffer, &indexBufferMemory.memory,
|
||||||
|
&renderPass, &pipelines[R2Render].pipeline, //&pipelines[blendToSC].pipeline,
|
||||||
|
&imageSampler, &framebuffers, &renderImages, &renderImageViews, // missing: &renderImageMemory,
|
||||||
|
&commandBuffers);
|
||||||
rLog("Created Renderer2D");
|
rLog("Created Renderer2D");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,6 +75,10 @@ namespace gz::vlk {
|
|||||||
// UPDATE DOC ON CHANGES!
|
// UPDATE DOC ON CHANGES!
|
||||||
|
|
||||||
/* vk.destroyCommandBuffers(commandBuffers); */
|
/* vk.destroyCommandBuffers(commandBuffers); */
|
||||||
|
#ifdef RENDERER_2D_ENABLE_SAMPLE_FROM_RENDER_IMAGES
|
||||||
|
vk.getDevice().destroyDescriptorPool(descriptorPool);
|
||||||
|
vk.getDevice().destroyDescriptorSetLayout(sampleFromRenderImageDSL);
|
||||||
|
#endif
|
||||||
cleanupSwapChainDependantResources();
|
cleanupSwapChainDependantResources();
|
||||||
cleanup_();
|
cleanup_();
|
||||||
}
|
}
|
||||||
@ -59,6 +90,9 @@ namespace gz::vlk {
|
|||||||
void Renderer2D::initSwapChainDependantResources() {
|
void Renderer2D::initSwapChainDependantResources() {
|
||||||
createRenderPass();
|
createRenderPass();
|
||||||
createImageResources();
|
createImageResources();
|
||||||
|
#ifdef RENDERER_2D_ENABLE_SAMPLE_FROM_RENDER_IMAGES
|
||||||
|
createDescriptorSetSampler();
|
||||||
|
#endif
|
||||||
vk.createFramebuffers(framebuffers, renderImageViews, renderPass);
|
vk.createFramebuffers(framebuffers, renderImageViews, renderPass);
|
||||||
std::vector<vk::DescriptorSetLayout> descriptorSetLayouts = { textureManager.getDescriptorSetLayout() };
|
std::vector<vk::DescriptorSetLayout> descriptorSetLayouts = { textureManager.getDescriptorSetLayout() };
|
||||||
|
|
||||||
@ -92,7 +126,7 @@ namespace gz::vlk {
|
|||||||
.stage = vk::ShaderStageFlagBits::eFragment,
|
.stage = vk::ShaderStageFlagBits::eFragment,
|
||||||
.module = fragShaderModule,
|
.module = fragShaderModule,
|
||||||
.pName = "main",
|
.pName = "main",
|
||||||
.pSpecializationInfo = nullptr,
|
.pSpecializationInfo = &specI,
|
||||||
});
|
});
|
||||||
|
|
||||||
vk::GraphicsPipelineCreateInfo pipelineCI {
|
vk::GraphicsPipelineCreateInfo pipelineCI {
|
||||||
@ -101,7 +135,12 @@ namespace gz::vlk {
|
|||||||
};
|
};
|
||||||
pipelineCI.setStages(shaderStages);
|
pipelineCI.setStages(shaderStages);
|
||||||
|
|
||||||
vk.createGraphicsPipeline<Vertex3D>(std::move(pipelineCI), &descriptorSetLayouts, true, pipelines[R2Render]);
|
std::vector<vk::PushConstantRange> pushConstantRanges;
|
||||||
|
pushConstantRanges.emplace_back(vk::PushConstantRange{
|
||||||
|
.stageFlags = vk::ShaderStageFlagBits::eFragment,
|
||||||
|
.size = sizeof(uint32_t),
|
||||||
|
});
|
||||||
|
vk.createGraphicsPipeline<Vertex2D>(std::move(pipelineCI), descriptorSetLayouts, pushConstantRanges, false, pipelines[R2Render]);
|
||||||
|
|
||||||
vk.getDevice().destroyShaderModule(vertShaderModule, nullptr);
|
vk.getDevice().destroyShaderModule(vertShaderModule, nullptr);
|
||||||
vk.getDevice().destroyShaderModule(fragShaderModule, nullptr);
|
vk.getDevice().destroyShaderModule(fragShaderModule, nullptr);
|
||||||
@ -114,7 +153,7 @@ namespace gz::vlk {
|
|||||||
|
|
||||||
vk.destroyFramebuffers(framebuffers);
|
vk.destroyFramebuffers(framebuffers);
|
||||||
|
|
||||||
#ifndef RENDERER_2D_RENDER_TO_SWAP_CHAIN
|
#ifdef RENDERER_2D_RENDER_TO_OWN_IMAGES
|
||||||
for (size_t i = 0; i < renderImages.size(); i++) {
|
for (size_t i = 0; i < renderImages.size(); i++) {
|
||||||
vk.destroyImageView(renderImageViews[i]);
|
vk.destroyImageView(renderImageViews[i]);
|
||||||
vk.destroyImage(renderImages[i], renderImageMemory[i]);
|
vk.destroyImage(renderImages[i], renderImageMemory[i]);
|
||||||
@ -135,22 +174,34 @@ namespace gz::vlk {
|
|||||||
//
|
//
|
||||||
void Renderer2D::createImageResources() {
|
void Renderer2D::createImageResources() {
|
||||||
renderImageViews.resize(vk.getScImages().size());
|
renderImageViews.resize(vk.getScImages().size());
|
||||||
#ifndef RENDERER_2D_RENDER_TO_SWAP_CHAIN
|
#ifdef RENDERER_2D_RENDER_TO_OWN_IMAGES
|
||||||
renderImages.resize(vk.getScImages().size());
|
renderImages.resize(vk.getScImages().size());
|
||||||
renderImageMemory.resize(vk.getScImages().size());
|
renderImageMemory.resize(vk.getScImages().size());
|
||||||
vk::ImageUsageFlags usage= vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc;
|
vk::ImageUsageFlags usage = vk::ImageUsageFlagBits::eColorAttachment;
|
||||||
|
#ifdef RENDERER_2D_SAMPLE_FROM_RENDER_IMAGES
|
||||||
|
usage |= vk::ImageUsageFlagBits::eSampled;
|
||||||
|
#elif defined RENDERER_2D_COPY_TO_SWAP_CHAIN
|
||||||
|
usage |= vk::ImageUsageFlagBits::eTransferSrc;
|
||||||
|
#endif
|
||||||
|
rLog.log("Image usage flags:", usage);
|
||||||
for (size_t i = 0; i < renderImages.size(); i++) {
|
for (size_t i = 0; i < renderImages.size(); i++) {
|
||||||
vk.createImage(vk.getScExtent().width, vk.getScExtent().height, vk.getScImageFormat(), vk::ImageTiling::eOptimal, usage, vk::MemoryPropertyFlagBits::eDeviceLocal, renderImages[i], renderImageMemory[i]);
|
vk.createImage(vk.getScExtent().width, vk.getScExtent().height, vk.getScImageFormat(), vk::ImageTiling::eOptimal, usage, vk::MemoryPropertyFlagBits::eDeviceLocal, renderImages[i], renderImageMemory[i]);
|
||||||
|
}
|
||||||
|
#ifdef RENDERER_2D_SAMPLE_FROM_RENDER_IMAGES
|
||||||
|
vk.createTextureSampler(imageSampler);
|
||||||
|
#endif
|
||||||
|
for (size_t i = 0; i < renderImages.size(); i++) {
|
||||||
vk.createImageView(vk.getScImageFormat(), renderImages[i], renderImageViews[i], vk::ImageAspectFlagBits::eColor);
|
vk.createImageView(vk.getScImageFormat(), renderImages[i], renderImageViews[i], vk::ImageAspectFlagBits::eColor);
|
||||||
}
|
}
|
||||||
vk.createTextureSampler(imageSampler);
|
|
||||||
rLog.log0("createImageResources: created images, views and sampler");
|
rLog.log0("createImageResources: created images, views and sampler");
|
||||||
#else
|
#elif defined RENDERER_2D_RENDER_TO_SWAP_CHAIN
|
||||||
for (size_t i = 0; i < renderImages.size(); i++) {
|
// views to swap chain images
|
||||||
|
for (size_t i = 0; i < renderImageViews.size(); i++) {
|
||||||
vk.createImageView(vk.getScImageFormat(), vk.getScImages()[i], renderImageViews[i], vk::ImageAspectFlagBits::eColor);
|
vk.createImageView(vk.getScImageFormat(), vk.getScImages()[i], renderImageViews[i], vk::ImageAspectFlagBits::eColor);
|
||||||
}
|
}
|
||||||
rLog.log0("createImageResources: created image views");
|
rLog.log0("createImageResources: created image views");
|
||||||
#endif
|
#endif
|
||||||
|
assert(renderImageViews.size() == vk.getScImages().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -165,7 +216,13 @@ namespace gz::vlk {
|
|||||||
.stencilLoadOp = vk::AttachmentLoadOp::eDontCare,
|
.stencilLoadOp = vk::AttachmentLoadOp::eDontCare,
|
||||||
.stencilStoreOp = vk::AttachmentStoreOp::eDontCare,
|
.stencilStoreOp = vk::AttachmentStoreOp::eDontCare,
|
||||||
.initialLayout = vk::ImageLayout::eUndefined,
|
.initialLayout = vk::ImageLayout::eUndefined,
|
||||||
|
#ifdef RENDERER_2D_ENABLE_SAMPLE_FROM_RENDER_IMAGES
|
||||||
|
.finalLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
||||||
|
#elif defined RENDERER_2D_COPY_TO_SWAP_CHAIN
|
||||||
.finalLayout = vk::ImageLayout::eTransferSrcOptimal,
|
.finalLayout = vk::ImageLayout::eTransferSrcOptimal,
|
||||||
|
#else
|
||||||
|
.finalLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
vk::AttachmentReference2 colorAttachmentRef {
|
vk::AttachmentReference2 colorAttachmentRef {
|
||||||
@ -173,21 +230,7 @@ namespace gz::vlk {
|
|||||||
.layout = vk::ImageLayout::eColorAttachmentOptimal,
|
.layout = vk::ImageLayout::eColorAttachmentOptimal,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* vk::AttachmentDescription depthAttachment { */
|
// SUBPASS: Rendering
|
||||||
/* depthAttachment.format = findDepthFormat(); */
|
|
||||||
/* depthAttachment.samples = vk::SampleCountFlagBits::e1; */
|
|
||||||
/* depthAttachment.loadOp = vk::AttachmentLoadOp::eClear; */
|
|
||||||
/* depthAttachment.storeOp = vk::AttachmentStoreOp::eDontCare; */
|
|
||||||
/* depthAttachment.stencilLoadOp = vk::AttachmentLoadOp::eDontCare; */
|
|
||||||
/* depthAttachment.stencilStoreOp = vk::AttachmentStoreOp::eDontCare; */
|
|
||||||
/* depthAttachment.initialLayout = vk::ImageLayout::eUndefined; */
|
|
||||||
/* depthAttachment.finalLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal; */
|
|
||||||
|
|
||||||
/* vk::AttachmentReference depthAttachmentRef { */
|
|
||||||
/* depthAttachmentRef.attachment = 1; */
|
|
||||||
/* depthAttachmentRef.layout = vk::ImageLayout::eDepthStencilAttachmentOptimal; */
|
|
||||||
|
|
||||||
// SUBPASS 1: DRAW STUFF
|
|
||||||
vk::SubpassDescription2 drawSubpass {
|
vk::SubpassDescription2 drawSubpass {
|
||||||
.pipelineBindPoint = vk::PipelineBindPoint::eGraphics,
|
.pipelineBindPoint = vk::PipelineBindPoint::eGraphics,
|
||||||
.colorAttachmentCount = 1,
|
.colorAttachmentCount = 1,
|
||||||
@ -205,36 +248,35 @@ namespace gz::vlk {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// dependecy for the image layout transition to transfer dst
|
// dependecy for the image layout transition to transfer dst
|
||||||
/* vk::SubpassDependency2 dsLayoutTransitionSD { */
|
vk::SubpassDependency2 dsLayoutTransitionSD {
|
||||||
|
.srcSubpass = 0,
|
||||||
|
.dstSubpass = VK_SUBPASS_EXTERNAL,
|
||||||
|
.srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput,
|
||||||
|
.dstStageMask = vk::PipelineStageFlagBits::eTransfer,
|
||||||
|
.srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite,
|
||||||
|
.dstAccessMask = vk::AccessFlagBits::eTransferRead,
|
||||||
|
.dependencyFlags = vk::DependencyFlagBits::eByRegion,
|
||||||
|
};
|
||||||
|
|
||||||
|
// SUBPASS 2: BLIT ONTO SWAP CHAIN IMAGE
|
||||||
|
/* vk::SubpassDescription2 blitSubpass { */
|
||||||
|
/* .pipelineBindPoint = vk::PipelineBindPoint::eGraphics, */
|
||||||
|
/* .colorAttachmentCount = 1, */
|
||||||
|
/* .pColorAttachments = &colorAttachmentRef, */
|
||||||
|
/* }; */
|
||||||
|
|
||||||
|
/* vk::SubpassDependency2 bsColorAttachmentSD { */
|
||||||
/* .srcSubpass = 0, */
|
/* .srcSubpass = 0, */
|
||||||
/* .dstSubpass = 1, */
|
/* .dstSubpass = 1, */
|
||||||
/* .srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput, */
|
/* .srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput, */
|
||||||
/* .dstStageMask = vk::PipelineStageFlagBits::eTransfer, */
|
/* .dstStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput, */
|
||||||
/* .srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite, */
|
/* .srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite, */
|
||||||
/* .dstAccessMask = vk::AccessFlagBits::eTransferRead, */
|
/* .dstAccessMask = vk::AccessFlagBits::eColorAttachmentRead, */
|
||||||
/* .dependencyFlags = vk::DependencyFlagBits::eByRegion, */
|
|
||||||
/* }; */
|
/* }; */
|
||||||
|
|
||||||
// SUBPASS 2: BLIT ONTO SWAP CHAIN IMAGE
|
|
||||||
vk::SubpassDescription2 blitSubpass {
|
|
||||||
.pipelineBindPoint = vk::PipelineBindPoint::eGraphics,
|
|
||||||
.colorAttachmentCount = 1,
|
|
||||||
.pColorAttachments = &colorAttachmentRef,
|
|
||||||
};
|
|
||||||
|
|
||||||
vk::SubpassDependency2 bsColorAttachmentSD {
|
|
||||||
.srcSubpass = 0,
|
|
||||||
.dstSubpass = 1,
|
|
||||||
.srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput,
|
|
||||||
.dstStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput,
|
|
||||||
.srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite,
|
|
||||||
.dstAccessMask = vk::AccessFlagBits::eColorAttachmentRead,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* std::array<vk::AttachmentDescription, 2> attachments = { colorBlendAttachment, depthAttachment }; */
|
|
||||||
std::vector<vk::AttachmentDescription2> attachments = { colorBlendAttachment };
|
std::vector<vk::AttachmentDescription2> attachments = { colorBlendAttachment };
|
||||||
std::vector<vk::SubpassDescription2> subpasses { drawSubpass, blitSubpass };
|
std::vector<vk::SubpassDescription2> subpasses { drawSubpass };
|
||||||
std::vector<vk::SubpassDependency2> dependencies = { dsColorAttachmentSD, bsColorAttachmentSD }; //dsLayoutTransitionSD };
|
std::vector<vk::SubpassDependency2> dependencies = { dsColorAttachmentSD, dsLayoutTransitionSD }; //, bsColorAttachmentSD }; //dsLayoutTransitionSD };
|
||||||
vk::RenderPassCreateInfo2 renderPassCI;
|
vk::RenderPassCreateInfo2 renderPassCI;
|
||||||
renderPassCI.setAttachments(attachments);
|
renderPassCI.setAttachments(attachments);
|
||||||
renderPassCI.setSubpasses(subpasses);
|
renderPassCI.setSubpasses(subpasses);
|
||||||
@ -247,18 +289,36 @@ namespace gz::vlk {
|
|||||||
rLog("createRenderPass: Created render pass.");
|
rLog("createRenderPass: Created render pass.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// DESCRIPTORS
|
||||||
|
//
|
||||||
|
void Renderer2D::createDescriptorResources() {
|
||||||
|
createDescriptorSetLayoutSampler(0);
|
||||||
|
// POOL
|
||||||
|
std::vector<vk::DescriptorPoolSize> poolSizes;
|
||||||
|
poolSizes = {
|
||||||
|
{ .type = vk::DescriptorType::eCombinedImageSampler, .descriptorCount = static_cast<uint32_t>(vk.getScImages().size()) },
|
||||||
|
};
|
||||||
|
uint32_t maxSets = 0;
|
||||||
|
for (auto& size : poolSizes) {
|
||||||
|
maxSets += size.descriptorCount;
|
||||||
|
}
|
||||||
|
vk.createDescriptorPool(poolSizes, maxSets, descriptorPool);
|
||||||
|
rLog("createDescriptorResources: pool", reinterpret_cast<uint64_t>(static_cast<VkDescriptorPool>(descriptorPool)), "vs hpp:", reinterpret_cast<uint64_t>(&(*descriptorPool)));
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// RENDERING
|
// RENDERING
|
||||||
//
|
//
|
||||||
void Renderer2D::recordCommandBuffer(uint32_t imageIndex, uint32_t currentFrame) {
|
void Renderer2D::beginFrameDraw(uint32_t imageIndex, uint32_t currentFrame) {
|
||||||
|
commandBuffers[currentFrame].reset();
|
||||||
vk::CommandBufferBeginInfo commandBufferBI {
|
vk::CommandBufferBeginInfo commandBufferBI {
|
||||||
/* .flags = 0, */
|
/* .flags = 0, */
|
||||||
/* .pInheritanceInfo = nullptr, */
|
/* .pInheritanceInfo = nullptr, */
|
||||||
};
|
};
|
||||||
vk::Result result = commandBuffers[currentFrame].begin(&commandBufferBI);
|
vk::Result result = commandBuffers[currentFrame].begin(&commandBufferBI);
|
||||||
if (result != vk::Result::eSuccess) {
|
if (result != vk::Result::eSuccess) {
|
||||||
throw getVkException(result, "Failed to begin 2D command buffer", "Renderer2D::recordCommandBuffer");
|
throw getVkException(result, "Failed to begin 2D command buffer", "Renderer2D::beginFrameDraw");
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear
|
// clear
|
||||||
@ -275,15 +335,90 @@ namespace gz::vlk {
|
|||||||
renderPassBI.setClearValues(clearValues);
|
renderPassBI.setClearValues(clearValues);
|
||||||
|
|
||||||
commandBuffers[currentFrame].beginRenderPass(&renderPassBI, vk::SubpassContents::eInline);
|
commandBuffers[currentFrame].beginRenderPass(&renderPassBI, vk::SubpassContents::eInline);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Renderer2D::endFrameDraw(uint32_t imageIndex, uint32_t currentFrame) {
|
||||||
|
commandBuffers[currentFrame].endRenderPass();
|
||||||
|
|
||||||
|
#ifdef RENDERER_2D_COPY_TO_SWAP_CHAIN
|
||||||
|
vk.copyImageToImage(commandBuffers[currentFrame], renderImages[imageIndex], vk.getScImages()[imageIndex], vk.getScExtent());
|
||||||
|
#endif
|
||||||
|
vk::Result result = commandBuffers[currentFrame].end();
|
||||||
|
if (result != vk::Result::eSuccess) {
|
||||||
|
rLog.error("Failed to record 2D - command buffer", "VkResult:", result);
|
||||||
|
throw getVkException(result, "Failed to record 2D - command buffer", "Renderer2D::endFrameDraw");
|
||||||
|
}
|
||||||
|
vk.submitThisFrame(commandBuffers[currentFrame]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* void Renderer2D::fillVertexBufferWithShapes() { */
|
||||||
|
/* rLog("fillVertexBufferWithShapes"); */
|
||||||
|
/* if (vertexBufferSize < shapesVerticesCount * sizeof(Vertex2D)) { */
|
||||||
|
/* throw VkException("vertex buffer too small! vertexBufferSize: " + std::to_string(vertexBufferSize) + ", required size: " + std::to_string(shapesVerticesCount), "fillVertexBufferWithShapes"); */
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
/* // create staging buffer */
|
||||||
|
/* vk::Buffer stagingBuffer; */
|
||||||
|
/* MemoryInfo stagingBufferMemory; */
|
||||||
|
/* vk.createBuffer(vertexBufferSize, vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent, stagingBuffer, stagingBufferMemory); */
|
||||||
|
|
||||||
|
/* // fill staging buffer */
|
||||||
|
/* void* data; */
|
||||||
|
/* vk::Result result = vk.getDevice().mapMemory(stagingBufferMemory.memory, stagingBufferMemory.offset, vertexBufferSize, NO_MEM_FLAGS, &data); */
|
||||||
|
/* if (result != vk::Result::eSuccess) { */
|
||||||
|
/* throw getVkException(result, "Failed to map staging buffer", "Renderer2D::fillVertexBufferWithShapes"); */
|
||||||
|
/* } */
|
||||||
|
/* Vertex2D* vdata = reinterpret_cast<Vertex2D*>(data); */
|
||||||
|
/* size_t offset = 0; */
|
||||||
|
/* for (auto it = shapes.begin(); it != shapes.end(); it++) { */
|
||||||
|
/* rLog.log0("fillVertexBufferWithShapes: copying vertex buffer nr", it - shapes.begin(), "-", it->getVertices(), "to address:", long(vdata + offset), " offset:", offset); */
|
||||||
|
/* memcpy(vdata+offset, it->getVertices().data(), it->getVertices().size() * sizeof(Vertex2D)); */
|
||||||
|
/* offset += it->getVertices().size(); */
|
||||||
|
/* } */
|
||||||
|
/* vk.getDevice().unmapMemory(stagingBufferMemory.memory); */
|
||||||
|
/* // fill vertex buffer */
|
||||||
|
/* vk.copyBuffer(stagingBuffer, vertexBuffer, vertexBufferSize); */
|
||||||
|
/* vk.destroyBuffer(stagingBuffer, stagingBufferMemory); */
|
||||||
|
/* } */
|
||||||
|
/* void Renderer2D::fillIndexBufferWithShapes() { */
|
||||||
|
/* rLog("fillIndexBufferWithShapes"); */
|
||||||
|
/* if (indexBufferSize < shapesIndicesCount * sizeof(uint32_t)) { */
|
||||||
|
/* throw VkException("index buffer too small! indexBufferSize: " + std::to_string(vertexBufferSize) + ", required size: " + std::to_string(shapesVerticesCount), "fillVertexBufferWithShapes"); */
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
/* // create staging buffer */
|
||||||
|
/* vk::Buffer stagingBuffer; */
|
||||||
|
/* MemoryInfo stagingBufferMemory; */
|
||||||
|
/* vk.createBuffer(indexBufferSize, vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent, stagingBuffer, stagingBufferMemory); */
|
||||||
|
|
||||||
|
/* // fill staging buffer */
|
||||||
|
/* void* data; */
|
||||||
|
/* vk::Result result = vk.getDevice().mapMemory(stagingBufferMemory.memory, stagingBufferMemory.offset, indexBufferSize, NO_MEM_FLAGS, &data); */
|
||||||
|
/* if (result != vk::Result::eSuccess) { */
|
||||||
|
/* throw getVkException(result, "Failed to map staging buffer", "Renderer2D::fillIndexBufferWithShapes"); */
|
||||||
|
/* } */
|
||||||
|
/* uint32_t* idata = reinterpret_cast<uint32_t*>(data); */
|
||||||
|
/* size_t offset = 0; */
|
||||||
|
/* for (auto it = shapes.begin(); it != shapes.end(); it++) { */
|
||||||
|
/* rLog("fillIndexBufferWithShapes: copying index buffer nr", it - shapes.begin(), "-", it->getIndices(), "to address:", long(idata + offset), " offset:", offset); */
|
||||||
|
/* memcpy(idata+offset, it->getIndices().data(), it->getIndices().size() * sizeof(uint32_t)); */
|
||||||
|
/* offset += it->getIndices().size(); */
|
||||||
|
/* } */
|
||||||
|
/* rLog.log0("fillIndexBufferWithShapes: indices count:", shapesIndicesCount); */
|
||||||
|
/* vk.getDevice().unmapMemory(stagingBufferMemory.memory); */
|
||||||
|
|
||||||
|
/* // fill index buffer */
|
||||||
|
/* vk.copyBuffer(stagingBuffer, indexBuffer, indexBufferSize); */
|
||||||
|
/* vk.destroyBuffer(stagingBuffer, stagingBufferMemory); */
|
||||||
|
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
|
||||||
|
void Renderer2D::drawShape(Shape* shape, uint32_t imageIndex, uint32_t currentFrame) {
|
||||||
|
/* rLog.log0("drawShape:", shape->getVertexBufferInfo(), shape->getIndexBufferInfo()); */
|
||||||
commandBuffers[currentFrame].bindPipeline(vk::PipelineBindPoint::eGraphics, pipelines[R2Render].pipeline);
|
commandBuffers[currentFrame].bindPipeline(vk::PipelineBindPoint::eGraphics, pipelines[R2Render].pipeline);
|
||||||
vk::Buffer vertexBuffers[] = { vertexBuffer };
|
|
||||||
vk::DeviceSize offsets[] = {0};
|
|
||||||
uint32_t bindingCount = 1;
|
|
||||||
uint32_t binding = 0;
|
|
||||||
commandBuffers[currentFrame].bindVertexBuffers(binding, bindingCount, vertexBuffers, offsets);
|
|
||||||
// TODO use correct index type!
|
|
||||||
commandBuffers[currentFrame].bindIndexBuffer(indexBuffer, NO_OFFSET, vk::IndexType::eUint32);
|
|
||||||
|
|
||||||
uint32_t descriptorCount = 1;
|
uint32_t descriptorCount = 1;
|
||||||
uint32_t firstSet = 0;
|
uint32_t firstSet = 0;
|
||||||
@ -291,103 +426,36 @@ namespace gz::vlk {
|
|||||||
uint32_t* dynamicOffsets = nullptr;
|
uint32_t* dynamicOffsets = nullptr;
|
||||||
commandBuffers[currentFrame].bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelines[R2Render].layout, firstSet, descriptorCount, &textureManager.getDescriptorSet(), dynamicOffsetCount, dynamicOffsets);
|
commandBuffers[currentFrame].bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelines[R2Render].layout, firstSet, descriptorCount, &textureManager.getDescriptorSet(), dynamicOffsetCount, dynamicOffsets);
|
||||||
|
|
||||||
int instanceCount = 1;
|
|
||||||
int firstIndex = 0;
|
|
||||||
int firstInstance = 0;
|
|
||||||
commandBuffers[currentFrame].drawIndexed(static_cast<uint32_t>(shapesIndicesCount), instanceCount, firstIndex, NO_OFFSET, firstInstance);
|
|
||||||
commandBuffers[currentFrame].endRenderPass();
|
|
||||||
|
|
||||||
/* vk.copyImageToImage(commandBuffers[currentFrame], images[imageIndex], vk.getScImages()[imageIndex], vk.getScExtent()); */
|
vk::Buffer vertexBuffers[] = { shapeBufferManager.getVertexBuffer(shape->getVertexBufferInfo()) };
|
||||||
result = commandBuffers[currentFrame].end();
|
vk::DeviceSize vertexOffsets[] = { shape->getVertexBufferInfo().offset };
|
||||||
if (result != vk::Result::eSuccess) {
|
uint32_t bindingCount = 1;
|
||||||
rLog.error("Failed to record 2D - command buffer", "VkResult:", result);
|
uint32_t binding = 0;
|
||||||
throw getVkException(result, "Failed to record 2D - command buffer", "Renderer2D::recordCommandBufferWithTexture");
|
|
||||||
}
|
commandBuffers[currentFrame].bindVertexBuffers(binding, bindingCount, vertexBuffers, vertexOffsets);
|
||||||
vk.submitThisFrame(commandBuffers[currentFrame]);
|
|
||||||
|
vk::Buffer indexBuffers = { shapeBufferManager.getIndexBuffer(shape->getIndexBufferInfo()) };
|
||||||
|
vk::DeviceSize indexOffset = shape->getIndexBufferInfo().offset;
|
||||||
|
// TODO use correct index type!
|
||||||
|
commandBuffers[currentFrame].bindIndexBuffer(indexBuffers, indexOffset, vk::IndexType::eUint32);
|
||||||
|
|
||||||
|
uint32_t pushConstant = shape->getTexureAtlasIndex();
|
||||||
|
vk::ShaderStageFlags flags(vk::ShaderStageFlagBits::eFragment);
|
||||||
|
commandBuffers[currentFrame].pushConstants(pipelines[R2Render].layout, flags, NO_OFFSET, sizeof(uint32_t), &pushConstant);
|
||||||
|
|
||||||
|
uint32_t indexCount = shape->getIndexBufferInfo().count;
|
||||||
|
uint32_t instanceCount = 1;
|
||||||
|
uint32_t firstIndex = 0;
|
||||||
|
uint32_t firstInstance = 0;
|
||||||
|
commandBuffers[currentFrame].drawIndexed(indexCount, instanceCount, firstIndex, NO_OFFSET, firstInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Renderer2D::initializeShape(Shape* shape) {
|
||||||
void Renderer2D::fillVertexBufferWithShapes() {
|
|
||||||
rLog("fillVertexBufferWithShapes");
|
|
||||||
if (vertexBufferSize < shapesVerticesCount * sizeof(Vertex2D)) {
|
|
||||||
throw VkException("vertex buffer too small! vertexBufferSize: " + std::to_string(vertexBufferSize) + ", required size: " + std::to_string(shapesVerticesCount), "fillVertexBufferWithShapes");
|
|
||||||
}
|
|
||||||
|
|
||||||
// create staging buffer
|
|
||||||
vk::Buffer stagingBuffer;
|
|
||||||
MemoryInfo stagingBufferMemory;
|
|
||||||
vk.createBuffer(vertexBufferSize, vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent, stagingBuffer, stagingBufferMemory);
|
|
||||||
|
|
||||||
// fill staging buffer
|
|
||||||
void* data;
|
|
||||||
vk::Result result = vk.getDevice().mapMemory(stagingBufferMemory.memory, stagingBufferMemory.offset, vertexBufferSize, NO_MEM_FLAGS, &data);
|
|
||||||
if (result != vk::Result::eSuccess) {
|
|
||||||
throw getVkException(result, "Failed to map staging buffer", "Renderer3D::fillVertexBufferWithShapes");
|
|
||||||
}
|
|
||||||
Vertex2D* vdata = reinterpret_cast<Vertex2D*>(data);
|
|
||||||
size_t offset = 0;
|
|
||||||
for (auto it = shapes.begin(); it != shapes.end(); it++) {
|
|
||||||
rLog.log0("fillVertexBufferWithShapes: copying vertex buffer nr", it - shapes.begin(), "-", it->getVertices(), "to address:", long(vdata + offset), " offset:", offset);
|
|
||||||
memcpy(vdata+offset, it->getVertices().data(), it->getVertices().size() * sizeof(Vertex2D));
|
|
||||||
offset += it->getVertices().size();
|
|
||||||
}
|
|
||||||
vk.getDevice().unmapMemory(stagingBufferMemory.memory);
|
|
||||||
// fill vertex buffer
|
|
||||||
vk.copyBuffer(stagingBuffer, vertexBuffer, vertexBufferSize);
|
|
||||||
vk.destroyBuffer(stagingBuffer, stagingBufferMemory);
|
|
||||||
}
|
|
||||||
void Renderer2D::fillIndexBufferWithShapes() {
|
|
||||||
rLog("fillIndexBufferWithShapes");
|
|
||||||
if (indexBufferSize < shapesIndicesCount * sizeof(uint32_t)) {
|
|
||||||
throw VkException("index buffer too small! indexBufferSize: " + std::to_string(vertexBufferSize) + ", required size: " + std::to_string(shapesVerticesCount), "fillVertexBufferWithShapes");
|
|
||||||
}
|
|
||||||
|
|
||||||
// create staging buffer
|
|
||||||
vk::Buffer stagingBuffer;
|
|
||||||
MemoryInfo stagingBufferMemory;
|
|
||||||
vk.createBuffer(indexBufferSize, vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent, stagingBuffer, stagingBufferMemory);
|
|
||||||
|
|
||||||
// fill staging buffer
|
|
||||||
void* data;
|
|
||||||
vk::Result result = vk.getDevice().mapMemory(stagingBufferMemory.memory, stagingBufferMemory.offset, indexBufferSize, NO_MEM_FLAGS, &data);
|
|
||||||
if (result != vk::Result::eSuccess) {
|
|
||||||
throw getVkException(result, "Failed to map staging buffer", "Renderer2D::fillIndexBufferWithShapes");
|
|
||||||
}
|
|
||||||
uint32_t* idata = reinterpret_cast<uint32_t*>(data);
|
|
||||||
size_t offset = 0;
|
|
||||||
for (auto it = shapes.begin(); it != shapes.end(); it++) {
|
|
||||||
rLog("fillIndexBufferWithShapes: copying index buffer nr", it - shapes.begin(), "-", it->getIndices(), "to address:", long(idata + offset), " offset:", offset);
|
|
||||||
memcpy(idata+offset, it->getIndices().data(), it->getIndices().size() * sizeof(uint32_t));
|
|
||||||
offset += it->getIndices().size();
|
|
||||||
}
|
|
||||||
rLog.log0("fillIndexBufferWithShapes: indices count:", shapesIndicesCount);
|
|
||||||
vk.getDevice().unmapMemory(stagingBufferMemory.memory);
|
|
||||||
|
|
||||||
// fill index buffer
|
|
||||||
vk.copyBuffer(stagingBuffer, indexBuffer, indexBufferSize);
|
|
||||||
vk.destroyBuffer(stagingBuffer, stagingBufferMemory);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Renderer2D::drawShape(Shape* shape) {
|
|
||||||
// make indices valid
|
// make indices valid
|
||||||
shape->setIndexOffset(shapesVerticesCount);
|
/* shape->setIndexOffset(shapesVerticesCount); */
|
||||||
shape->normalizeVertices(vk.getScExtent().width, vk.getScExtent().height);
|
shape->normalizeVertices(vk.getScExtent().width, vk.getScExtent().height);
|
||||||
shape->setTextureCoordinates(textureManager);
|
shape->setTextureCoordinates(textureManager);
|
||||||
// object slicing here, need to call virtual setTextureCoordinates before this!
|
shape->initalizeBufferInfos(shapeBufferManager);
|
||||||
shapes.push_back(*shape);
|
|
||||||
shapesVerticesCount += shape->getVertices().size();
|
|
||||||
shapesIndicesCount += shape->getIndices().size();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Renderer2D::drawFrame(uint32_t imageIndex) {
|
|
||||||
commandBuffers[vk.getCurrentFrame()].reset();
|
|
||||||
/* recordCommandBuffer(imageIndex, vk.getCurrentFrame()); */
|
|
||||||
recordCommandBuffer(imageIndex, vk.getCurrentFrame());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace gz::vlk
|
} // namespace gz::vlk
|
||||||
|
@ -11,6 +11,15 @@ namespace gz::vlk {
|
|||||||
R2Render,
|
R2Render,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 2D Renderer
|
||||||
|
* @details
|
||||||
|
* @section r3d_options Options
|
||||||
|
* - `RENDERER_2D_RENDER_TO_OWN_IMAGES`: render to own images
|
||||||
|
* - `RENDERER_2D_COPY_TO_SWAP_CHAIN`: copy the image to the swap chain after rendering it to the own image (swap chain images have to be created with TRANSFER_DST_BIT)
|
||||||
|
* - `RENDERER_2D_SAMPLE_FROM_RENDER_IMAGES`: enable sampling from the rendered images
|
||||||
|
* - `RENDERER_2D_RENDER_TO_SWAP_CHAIN`: render directly onto the swap chain
|
||||||
|
*/
|
||||||
class Renderer2D : public Renderer {
|
class Renderer2D : public Renderer {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@ -20,6 +29,7 @@ namespace gz::vlk {
|
|||||||
* -# @ref VulkanInstance::registerSwapChainRecreateCallback "register" @ref swapChainRecreateCallback "swapChain recreation callback"
|
* -# @ref VulkanInstance::registerSwapChainRecreateCallback "register" @ref swapChainRecreateCallback "swapChain recreation callback"
|
||||||
* -# create command buffers
|
* -# create command buffers
|
||||||
* -# create vertex & index buffers
|
* -# create vertex & index buffers
|
||||||
|
* -# call createDescriptorResources (if `RENDERER_2D_SAMPLE_FROM_RENDER_IMAGES`)
|
||||||
* -# call initSwapChainDependantResources
|
* -# call initSwapChainDependantResources
|
||||||
*/
|
*/
|
||||||
Renderer2D(VulkanInstance& instance, TextureManager& textureManager);
|
Renderer2D(VulkanInstance& instance, TextureManager& textureManager);
|
||||||
@ -27,13 +37,30 @@ namespace gz::vlk {
|
|||||||
* @name Rendering
|
* @name Rendering
|
||||||
*/
|
*/
|
||||||
/// @{
|
/// @{
|
||||||
void drawShape(Shape* shape);
|
/**
|
||||||
|
* @brief Begin rendering a new frame
|
||||||
|
* @details
|
||||||
|
* As of now, this does (in the same command buffer from graphicsPool)
|
||||||
|
* -# begin render pass
|
||||||
|
* - image layout: vk::ImageLayout::eColorAttachmentOptimal
|
||||||
|
* - clear image
|
||||||
|
*/
|
||||||
|
void beginFrameDraw(uint32_t imageIndex, uint32_t currentFrame);
|
||||||
|
/**
|
||||||
|
* @brief End rendering a frame
|
||||||
|
* -# end render pass
|
||||||
|
* - image layout: vk::ImageLayout::eTransferSrcOptimal
|
||||||
|
* -# copy image to swapChain image with same imageIndex (if RENDERER_2D_COPY_TO_SWAP_CHAIN)
|
||||||
|
*/
|
||||||
|
void endFrameDraw(uint32_t imageIndex, uint32_t currentFrame);
|
||||||
|
|
||||||
|
void drawShape(Shape* shape, uint32_t imageIndex, uint32_t currentFrame);
|
||||||
|
void initializeShape(Shape* shape);
|
||||||
/**
|
/**
|
||||||
* @brief Copies the vertices from shapes into the vertex buffer, using a staging buffer
|
* @brief Copies the vertices from shapes into the vertex buffer, using a staging buffer
|
||||||
*/
|
*/
|
||||||
void fillVertexBufferWithShapes();
|
/* void fillVertexBufferWithShapes(); */
|
||||||
void fillIndexBufferWithShapes();
|
/* void fillIndexBufferWithShapes(); */
|
||||||
void drawFrame(uint32_t imageIndex);
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -41,28 +68,18 @@ namespace gz::vlk {
|
|||||||
* @brief Destroy all vulkan objects owned by this object
|
* @brief Destroy all vulkan objects owned by this object
|
||||||
* @details:
|
* @details:
|
||||||
* Does:
|
* Does:
|
||||||
|
* -# destroy descriptor layout and pool (if `RENDERER_2D_SAMPLE_FROM_RENDER_IMAGES`)
|
||||||
* -# call cleanupSwapChainDependantResources()
|
* -# call cleanupSwapChainDependantResources()
|
||||||
* -# call Renderer::cleanup_()
|
* -# call Renderer::cleanup_()
|
||||||
*/
|
*/
|
||||||
void cleanup();
|
void cleanup();
|
||||||
std::vector<Shape> shapes;
|
|
||||||
size_t shapesVerticesCount = 0;
|
/* std::vector<Shape> shapes; */
|
||||||
size_t shapesIndicesCount = 0;
|
/* size_t shapesVerticesCount = 0; */
|
||||||
/**
|
/* size_t shapesIndicesCount = 0; */
|
||||||
* @brief Render everything
|
BufferManager<Vertex2D, uint32_t> shapeBufferManager;
|
||||||
* @details
|
|
||||||
* As of now, this does (in the same command buffer from graphicsPool)
|
/* void recordCommandBuffer(uint32_t imageIndex, uint32_t currentFrame); */
|
||||||
* -# begin render pass
|
|
||||||
* - image layout: vk::ImageLayout::eColorAttachmentOptimal
|
|
||||||
* - clear image
|
|
||||||
* -# bind 2d pipeline, vertex and index buffer
|
|
||||||
* -# bind texture sampler
|
|
||||||
* -# draw indexed: draw the shapes from shapes vector
|
|
||||||
* -# end render pass
|
|
||||||
* - image layout: vk::ImageLayout::eTransferSrcOptimal
|
|
||||||
* -# copy image to swapChain image with same imageIndex
|
|
||||||
*/
|
|
||||||
void recordCommandBuffer(uint32_t imageIndex, uint32_t currentFrame);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create the render image resources
|
* @brief Create the render image resources
|
||||||
@ -108,6 +125,23 @@ namespace gz::vlk {
|
|||||||
// PIPELINE
|
// PIPELINE
|
||||||
PipelineContainer<Pipelines2D> pipelines;
|
PipelineContainer<Pipelines2D> pipelines;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Desciptors
|
||||||
|
* @details
|
||||||
|
*
|
||||||
|
* @section r2d_desc Descriptors
|
||||||
|
* Renderer2D has one descriptor set.
|
||||||
|
* @subsection r2d_desc1 Set 1: For sampling from the rendered image
|
||||||
|
* If `RENDERER_2D_ENABLE_SAMPLE_FROM_RENDER_IMAGES`:
|
||||||
|
* -0. Image sampler for current render image (DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
|
||||||
|
*/
|
||||||
|
/// @{
|
||||||
|
/**
|
||||||
|
* @brief Create descriptor pool and layout
|
||||||
|
*/
|
||||||
|
void createDescriptorResources();
|
||||||
|
/// @}
|
||||||
|
|
||||||
// SWAPCHAIN RECREATION
|
// SWAPCHAIN RECREATION
|
||||||
/**
|
/**
|
||||||
* @brief Swapchain recreation
|
* @brief Swapchain recreation
|
||||||
@ -120,9 +154,10 @@ namespace gz::vlk {
|
|||||||
/**
|
/**
|
||||||
* @brief Sets up resources that depend on the swap chain or its attributes
|
* @brief Sets up resources that depend on the swap chain or its attributes
|
||||||
* @details
|
* @details
|
||||||
* Initializes up:
|
* Initializes:
|
||||||
* - render pass
|
* - render pass
|
||||||
* - images, imageMemory, imageViews
|
* - images, imageMemory, imageViews
|
||||||
|
* - image sampling descriptor set (if `RENDERER_2D_SAMPLE_FROM_RENDER_IMAGES`)
|
||||||
* - framebuffers
|
* - framebuffers
|
||||||
* - pipeline
|
* - pipeline
|
||||||
*/
|
*/
|
||||||
|
@ -12,8 +12,34 @@
|
|||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <vulkan/vulkan_enums.hpp>
|
||||||
#include <vulkan/vulkan_structs.hpp>
|
#include <vulkan/vulkan_structs.hpp>
|
||||||
|
|
||||||
|
constexpr uint32_t DS_MVP_BINDING = 0;
|
||||||
|
|
||||||
|
/* #define RENDERER_3D_RENDER_TO_SWAP_CHAIN */
|
||||||
|
#define RENDERER_3D_RENDER_TO_OWN_IMAGES
|
||||||
|
#define RENDERER_3D_COPY_TO_SWAP_CHAIN
|
||||||
|
|
||||||
|
// options sanity checks
|
||||||
|
#ifdef RENDERER_3D_RENDER_TO_SWAP_CHAIN
|
||||||
|
#ifdef RENDERER_3D_RENDER_TO_OWN_IMAGES
|
||||||
|
static_assert(false, "RENDERER_3D_RENDER_TO_SWAP_CHAIN and RENDERER_3D_RENDER_TO_OWN_IMAGES defined at the same time");
|
||||||
|
#endif
|
||||||
|
#ifdef RENDERER_3D_COPY_TO_SWAP_CHAIN
|
||||||
|
static_assert(false, "RENDERER_3D_RENDER_TO_SWAP_CHAIN and RENDERER_3D_COPY_TO_SWAP_CHAIN defined at the same time");
|
||||||
|
#endif
|
||||||
|
#ifdef RENDERER_3D_ENABLE_SAMPLE_FROM_RENDER_IMAGES
|
||||||
|
static_assert(false, "RENDERER_3D_RENDER_TO_SWAP_CHAIN and RENDERER_3D_ENABLE_SAMPLE_FROM_RENDER_IMAGES defined at the same time");
|
||||||
|
#endif
|
||||||
|
#elif defined RENDERER_3D_RENDER_TO_OWN_IMAGES
|
||||||
|
/* #ifndef RENDERER_3D_COPY_TO_SWAP_CHAIN */
|
||||||
|
/* #define RENDERER_3D_ENABLE_SAMPLE_FROM_RENDER_IMAGES */
|
||||||
|
/* #endif */
|
||||||
|
#else
|
||||||
|
static_assert(false, "Either RENDERER_3D_RENDER_TO_OWN_IMAGES or RENDERER_3D_RENDER_TO_SWAP_CHAIN must be defined");
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace gz::vlk {
|
namespace gz::vlk {
|
||||||
//
|
//
|
||||||
// INIT & CLEANUP
|
// INIT & CLEANUP
|
||||||
@ -33,8 +59,8 @@ namespace gz::vlk {
|
|||||||
vk.registerSwapChainRecreateCallback(std::bind(&Renderer3D::swapChainRecreateCallback, this));
|
vk.registerSwapChainRecreateCallback(std::bind(&Renderer3D::swapChainRecreateCallback, this));
|
||||||
|
|
||||||
vk.createCommandBuffers(commandBuffers);
|
vk.createCommandBuffers(commandBuffers);
|
||||||
const size_t vertexCount = 20000;
|
const size_t vertexCount = 500000;
|
||||||
const size_t indexCount = 10000;
|
const size_t indexCount = 500000;
|
||||||
vk.createVertexBuffer<Vertex3D>(vertexCount, vertexBuffer, vertexBufferMemory, vertexBufferSize);
|
vk.createVertexBuffer<Vertex3D>(vertexCount, vertexBuffer, vertexBufferMemory, vertexBufferSize);
|
||||||
vk.createIndexBuffer<uint32_t>(indexCount, indexBuffer, indexBufferMemory, indexBufferSize);
|
vk.createIndexBuffer<uint32_t>(indexCount, indexBuffer, indexBufferMemory, indexBufferSize);
|
||||||
|
|
||||||
@ -43,13 +69,17 @@ namespace gz::vlk {
|
|||||||
|
|
||||||
createUniformBuffers();
|
createUniformBuffers();
|
||||||
createDescriptorResources();
|
createDescriptorResources();
|
||||||
|
createDescriptorSetMvp();
|
||||||
initSwapChainDependantResources();
|
initSwapChainDependantResources();
|
||||||
VulkanInstance::registerObjectUsingVulkan("Renderer3D",
|
VulkanInstance::registerObjectUsingVulkan("Renderer3D",
|
||||||
&renderPass, &imageSampler, &vertexBuffer, &vertexBufferMemory.memory, &indexBuffer, &indexBufferMemory.memory,
|
&vertexBuffer, &vertexBufferMemory.memory,
|
||||||
&pipelines[R3Render].pipeline, //&pipelines[blendToSC].pipeline,
|
&indexBuffer, &indexBufferMemory.memory,
|
||||||
&descriptorPool, &uboDSL, &sampleFromRenderImageDSL,
|
&renderPass, &pipelines[R3Render].pipeline, //&pipelines[blendToSC].pipeline,
|
||||||
&framebuffers, &renderImages, &renderImageViews, &commandBuffers,
|
&descriptorPool,
|
||||||
&uboDS, &sampleFromRenderImageDS); // missing: &renderImageMemory,
|
&mvpDSL, &sampleFromRenderImageDSL,
|
||||||
|
&mvpDS, &sampleFromRenderImageDS,
|
||||||
|
&imageSampler, &framebuffers, &renderImages, &renderImageViews, // missing: &renderImageMemory,
|
||||||
|
&commandBuffers);
|
||||||
rLog.log1("Created Renderer3D");
|
rLog.log1("Created Renderer3D");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,14 +89,16 @@ namespace gz::vlk {
|
|||||||
for (size_t i = 0; i < vk.getMaxFramesInFlight(); i++) {
|
for (size_t i = 0; i < vk.getMaxFramesInFlight(); i++) {
|
||||||
vk.destroyBuffer(uniformBuffers[i], uniformBuffersMemory[i]);
|
vk.destroyBuffer(uniformBuffers[i], uniformBuffersMemory[i]);
|
||||||
}
|
}
|
||||||
vk.getDevice().destroyDescriptorSetLayout(uboDSL, NO_ALLOC);
|
vk.getDevice().destroyDescriptorSetLayout(mvpDSL, NO_ALLOC);
|
||||||
vk.getDevice().destroyDescriptorPool(descriptorPool, NO_ALLOC);
|
vk.getDevice().destroyDescriptorPool(descriptorPool, NO_ALLOC);
|
||||||
|
|
||||||
|
#ifdef RENDERER_3D_SAMPLE_FROM_RENDER_IMAGES
|
||||||
|
vk.getDevice().destroySampler(imageSampler);
|
||||||
|
#endif
|
||||||
|
|
||||||
cleanupSwapChainDependantResources();
|
cleanupSwapChainDependantResources();
|
||||||
cleanup_();
|
cleanup_();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// SWAPCHAIN DEPENDANT
|
// SWAPCHAIN DEPENDANT
|
||||||
//
|
//
|
||||||
@ -75,64 +107,12 @@ namespace gz::vlk {
|
|||||||
createRenderPass();
|
createRenderPass();
|
||||||
createDepthImage();
|
createDepthImage();
|
||||||
createImageResources();
|
createImageResources();
|
||||||
|
#ifdef RENDERER_3D_ENABLE_SAMPLE_FROM_RENDER_IMAGES
|
||||||
|
createDescriptorSetSampler();
|
||||||
|
#endif
|
||||||
vk.createFramebuffers(framebuffers, renderImageViews, renderPass, depthImageView);
|
vk.createFramebuffers(framebuffers, renderImageViews, renderPass, depthImageView);
|
||||||
|
createPipelines();
|
||||||
|
|
||||||
// VERTEX 3D PIPELINE
|
|
||||||
std::vector<vk::DescriptorSetLayout> descriptorSetLayouts = { uboDSL, textureManager.getDescriptorSetLayout() };
|
|
||||||
auto vertShaderCode = readBinaryFile("shaders/shader.vert.spv");
|
|
||||||
auto fragShaderCode = readBinaryFile("shaders/shader.frag.spv");
|
|
||||||
|
|
||||||
vk::ShaderModule vertShaderModule = vk.createShaderModule(vertShaderCode);
|
|
||||||
vk::ShaderModule fragShaderModule = vk.createShaderModule(fragShaderCode);
|
|
||||||
|
|
||||||
std::vector<vk::PipelineShaderStageCreateInfo> shaderStages;
|
|
||||||
|
|
||||||
shaderStages.emplace_back(vk::PipelineShaderStageCreateInfo {
|
|
||||||
.stage = vk::ShaderStageFlagBits::eVertex,
|
|
||||||
.module = vertShaderModule,
|
|
||||||
.pName = "main",
|
|
||||||
.pSpecializationInfo = nullptr,
|
|
||||||
});
|
|
||||||
shaderStages.emplace_back(vk::PipelineShaderStageCreateInfo {
|
|
||||||
.stage = vk::ShaderStageFlagBits::eFragment,
|
|
||||||
.module = fragShaderModule,
|
|
||||||
.pName = "main",
|
|
||||||
.pSpecializationInfo = nullptr,
|
|
||||||
});
|
|
||||||
|
|
||||||
vk::GraphicsPipelineCreateInfo pipelineCI {
|
|
||||||
.renderPass = renderPass,
|
|
||||||
.subpass = 0,
|
|
||||||
};
|
|
||||||
pipelineCI.setStages(shaderStages);
|
|
||||||
|
|
||||||
vk.createGraphicsPipeline<Vertex3D>(std::move(pipelineCI), &descriptorSetLayouts, true, pipelines[R3Render]);
|
|
||||||
|
|
||||||
vk.getDevice().destroyShaderModule(vertShaderModule, nullptr);
|
|
||||||
vk.getDevice().destroyShaderModule(fragShaderModule, nullptr);
|
|
||||||
|
|
||||||
|
|
||||||
// BLIT TO SWAP CHAIN PIPELINE
|
|
||||||
/* auto fragShaderCode2 = readBinaryFile("shaders/blend.frag.spv"); */
|
|
||||||
/* vk::ShaderModule fragShaderModule2 = vk.createShaderModule(fragShaderCode); */
|
|
||||||
|
|
||||||
/* std::vector<vk::PipelineShaderStageCreateInfo> shaderStages2; */
|
|
||||||
/* shaderStages2.emplace_back(vk::PipelineShaderStageCreateInfo { */
|
|
||||||
/* .stage = vk::ShaderStageFlagBits::eFragment, */
|
|
||||||
/* .module = fragShaderModule2, */
|
|
||||||
/* .pName = "main", */
|
|
||||||
/* .pSpecializationInfo = nullptr, */
|
|
||||||
/* }); */
|
|
||||||
|
|
||||||
/* vk::GraphicsPipelineCreateInfo pipelineCI2 { */
|
|
||||||
/* .renderPass = renderPass, */
|
|
||||||
/* .subpass = 1, */
|
|
||||||
/* }; */
|
|
||||||
/* pipelineCI2.setStages(shaderStages2); */
|
|
||||||
|
|
||||||
/* vk.createGraphicsPipeline<Vertex3D>(std::move(pipelineCI2), nullptr, false, pipelines[blendToSC]); */
|
|
||||||
|
|
||||||
/* vk.getDevice().destroyShaderModule(fragShaderModule2, nullptr); */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -145,7 +125,7 @@ namespace gz::vlk {
|
|||||||
vk.destroyImageView(depthImageView);
|
vk.destroyImageView(depthImageView);
|
||||||
vk.destroyImage(depthImage, depthImageMemory);
|
vk.destroyImage(depthImage, depthImageMemory);
|
||||||
|
|
||||||
#ifndef RENDERER_3D_RENDER_TO_SWAP_CHAIN
|
#ifdef RENDERER_3D_RENDER_TO_OWN_IMAGES
|
||||||
for (size_t i = 0; i < renderImages.size(); i++) {
|
for (size_t i = 0; i < renderImages.size(); i++) {
|
||||||
vk.destroyImageView(renderImageViews[i]);
|
vk.destroyImageView(renderImageViews[i]);
|
||||||
vk.destroyImage(renderImages[i], renderImageMemory[i]);
|
vk.destroyImage(renderImages[i], renderImageMemory[i]);
|
||||||
@ -166,22 +146,30 @@ namespace gz::vlk {
|
|||||||
//
|
//
|
||||||
void Renderer3D::createImageResources() {
|
void Renderer3D::createImageResources() {
|
||||||
renderImageViews.resize(vk.getScImages().size());
|
renderImageViews.resize(vk.getScImages().size());
|
||||||
#ifndef RENDERER_3D_RENDER_TO_SWAP_CHAIN
|
#ifdef RENDERER_3D_RENDER_TO_OWN_IMAGES
|
||||||
renderImages.resize(vk.getScImages().size());
|
renderImages.resize(vk.getScImages().size());
|
||||||
renderImageMemory.resize(vk.getScImages().size());
|
renderImageMemory.resize(vk.getScImages().size());
|
||||||
vk::ImageUsageFlags usage= vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc;
|
vk::ImageUsageFlags usage = vk::ImageUsageFlagBits::eColorAttachment;
|
||||||
|
#ifdef RENDERER_3D_ENABLE_SAMPLE_FROM_RENDER_IMAGES
|
||||||
|
usage |= vk::ImageUsageFlagBits::eSampled;
|
||||||
|
#elif defined RENDERER_3D_COPY_TO_SWAP_CHAIN
|
||||||
|
usage |= vk::ImageUsageFlagBits::eTransferSrc;
|
||||||
|
#endif
|
||||||
for (size_t i = 0; i < renderImages.size(); i++) {
|
for (size_t i = 0; i < renderImages.size(); i++) {
|
||||||
vk.createImage(vk.getScExtent().width, vk.getScExtent().height, vk.getScImageFormat(), vk::ImageTiling::eOptimal, usage, vk::MemoryPropertyFlagBits::eDeviceLocal, renderImages[i], renderImageMemory[i]);
|
vk.createImage(vk.getScExtent().width, vk.getScExtent().height, vk.getScImageFormat(), vk::ImageTiling::eOptimal, usage, vk::MemoryPropertyFlagBits::eDeviceLocal, renderImages[i], renderImageMemory[i]);
|
||||||
vk.createImageView(vk.getScImageFormat(), renderImages[i], renderImageViews[i], vk::ImageAspectFlagBits::eColor);
|
vk.createImageView(vk.getScImageFormat(), renderImages[i], renderImageViews[i], vk::ImageAspectFlagBits::eColor);
|
||||||
}
|
}
|
||||||
|
#ifdef RENDERER_3D_SAMPLE_FROM_RENDER_IMAGES
|
||||||
vk.createTextureSampler(imageSampler);
|
vk.createTextureSampler(imageSampler);
|
||||||
|
#endif
|
||||||
rLog.log0("createImageResources: created images, views and sampler");
|
rLog.log0("createImageResources: created images, views and sampler");
|
||||||
#else
|
#elif defined RENDERER_3D_RENDER_TO_SWAP_CHAIN
|
||||||
for (size_t i = 0; i < renderImages.size(); i++) {
|
for (size_t i = 0; i < renderImageViews.size(); i++) {
|
||||||
vk.createImageView(vk.getScImageFormat(), vk.getScImages()[i], renderImageViews[i], vk::ImageAspectFlagBits::eColor);
|
vk.createImageView(vk.getScImageFormat(), vk.getScImages()[i], renderImageViews[i], vk::ImageAspectFlagBits::eColor);
|
||||||
}
|
}
|
||||||
rLog.log0("createImageResources: created image views");
|
rLog.log0("createImageResources: created image views");
|
||||||
#endif
|
#endif
|
||||||
|
assert(renderImageViews.size() == vk.getScImages().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -212,7 +200,13 @@ namespace gz::vlk {
|
|||||||
.stencilLoadOp = vk::AttachmentLoadOp::eDontCare,
|
.stencilLoadOp = vk::AttachmentLoadOp::eDontCare,
|
||||||
.stencilStoreOp = vk::AttachmentStoreOp::eDontCare,
|
.stencilStoreOp = vk::AttachmentStoreOp::eDontCare,
|
||||||
.initialLayout = vk::ImageLayout::eUndefined,
|
.initialLayout = vk::ImageLayout::eUndefined,
|
||||||
|
#ifdef RENDERER_3D_ENABLE_SAMPLE_FROM_RENDER_IMAGES
|
||||||
|
.finalLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
||||||
|
#elif defined RENDERER_3D_COPY_TO_SWAP_CHAIN
|
||||||
.finalLayout = vk::ImageLayout::eTransferSrcOptimal,
|
.finalLayout = vk::ImageLayout::eTransferSrcOptimal,
|
||||||
|
#else
|
||||||
|
.finalLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
vk::AttachmentReference2 colorBlendAR {
|
vk::AttachmentReference2 colorBlendAR {
|
||||||
@ -253,6 +247,7 @@ namespace gz::vlk {
|
|||||||
.dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eDepthStencilAttachmentWrite,
|
.dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eDepthStencilAttachmentWrite,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef RENDERER_3D_COPY_TO_SWAP_CHAIN
|
||||||
// image layout transition to transfer dst
|
// image layout transition to transfer dst
|
||||||
vk::SubpassDependency2 layoutTransitionSD {
|
vk::SubpassDependency2 layoutTransitionSD {
|
||||||
.srcSubpass = 0,
|
.srcSubpass = 0,
|
||||||
@ -263,29 +258,25 @@ namespace gz::vlk {
|
|||||||
.dstAccessMask = vk::AccessFlagBits::eTransferRead,
|
.dstAccessMask = vk::AccessFlagBits::eTransferRead,
|
||||||
.dependencyFlags = vk::DependencyFlagBits::eByRegion,
|
.dependencyFlags = vk::DependencyFlagBits::eByRegion,
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/* vk::SubpassDependency2 dependency { */
|
/* vk::SubpassDependency2 dependency { */
|
||||||
/* dependency.srcSubpass = VK_SUBPASS_EXTERNAL; */
|
/* .srcSubpass = VK_SUBPASS_EXTERNAL, */
|
||||||
/* dependency.dstSubpass = 0; */
|
/* .dstSubpass = 0, */
|
||||||
/* dependency.srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput | vk::PipelineStageFlagBits::eEarlyFragmentTests; */
|
/* .srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput | vk::PipelineStageFlagBits::eEarlyFragmentTests, */
|
||||||
/* dependency.srcAccessMask = 0; */
|
/* .dstStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput | vk::PipelineStageFlagBits::eEarlyFragmentTests, */
|
||||||
/* dependency.dstStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput | vk::PipelineStageFlagBits::eEarlyFragmentTests; */
|
/* .srcAccessMask = NO_ACC_FLAGS, */
|
||||||
/* dependency.dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eDepthStencilAttachmentWrite; */
|
/* .dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eDepthStencilAttachmentWrite, */
|
||||||
|
/* }; */
|
||||||
|
|
||||||
std::vector<vk::AttachmentDescription2> attachments = { colorBlendAD, depthAD, };
|
std::vector<vk::AttachmentDescription2> attachments = { colorBlendAD, depthAD, };
|
||||||
std::vector<vk::SubpassDependency2> dependencies = { colorAttachmentSD, layoutTransitionSD };
|
std::vector<vk::SubpassDependency2> dependencies = { colorAttachmentSD
|
||||||
vk::RenderPassCreateInfo2 renderPassCI {
|
#ifdef RENDERER_3D_COPY_TO_SWAP_CHAIN
|
||||||
/* .attachmentCount = static_cast<uint32_t>(attachments.size()), */
|
, layoutTransitionSD
|
||||||
/* .pAttachments = attachments.data(), */
|
#endif
|
||||||
/* .subpassCount = 1, */
|
|
||||||
/* .pSubpasses = &subpass, */
|
|
||||||
/* .dependencyCount = static_cast<uint32_t>(dependencies.size()), */
|
|
||||||
/* .pDependencies = dependencies.data(), */
|
|
||||||
/* .dependencyCount = 0, */
|
|
||||||
/* .pDependencies = nullptr, */
|
|
||||||
/* .correlatedViewMaskCount = 0, */
|
|
||||||
/* .pCorrelatedViewMasks = nullptr, */
|
|
||||||
};
|
};
|
||||||
|
vk::RenderPassCreateInfo2 renderPassCI;
|
||||||
|
/* renderPassCI.setCorrelatedViewMasks() */
|
||||||
renderPassCI.setAttachments(attachments);
|
renderPassCI.setAttachments(attachments);
|
||||||
renderPassCI.setDependencies(dependencies);
|
renderPassCI.setDependencies(dependencies);
|
||||||
renderPassCI.setSubpasses(subpass);
|
renderPassCI.setSubpasses(subpass);
|
||||||
@ -297,71 +288,153 @@ namespace gz::vlk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Renderer3D::createPipelines() {
|
||||||
|
// VERTEX 3D PIPELINE
|
||||||
|
std::vector<vk::DescriptorSetLayout> descriptorSetLayouts = { textureManager.getDescriptorSetLayout(), mvpDSL };
|
||||||
|
/* std::vector<vk::DescriptorSetLayout> descriptorSetLayouts = { mvpDSL }; */
|
||||||
|
|
||||||
|
// specialization constant for sampler2D array length = atlas count
|
||||||
|
vk::SpecializationMapEntry specME {
|
||||||
|
.constantID = 0,
|
||||||
|
.offset = 0,
|
||||||
|
.size = sizeof(uint32_t),
|
||||||
|
};
|
||||||
|
uint32_t atlasCount = textureManager.getAtlasCount();
|
||||||
|
vk::SpecializationInfo specI;
|
||||||
|
specI.setData<uint32_t>(atlasCount);
|
||||||
|
specI.setMapEntries(specME);
|
||||||
|
|
||||||
|
auto vertShaderCode = readBinaryFile("shaders/shader.vert.spv");
|
||||||
|
auto fragShaderCode = readBinaryFile("shaders/shader.frag.spv");
|
||||||
|
|
||||||
|
vk::ShaderModule vertShaderModule = vk.createShaderModule(vertShaderCode);
|
||||||
|
vk::ShaderModule fragShaderModule = vk.createShaderModule(fragShaderCode);
|
||||||
|
|
||||||
|
std::vector<vk::PipelineShaderStageCreateInfo> shaderStages;
|
||||||
|
|
||||||
|
shaderStages.emplace_back(vk::PipelineShaderStageCreateInfo {
|
||||||
|
.stage = vk::ShaderStageFlagBits::eVertex,
|
||||||
|
.module = vertShaderModule,
|
||||||
|
.pName = "main",
|
||||||
|
.pSpecializationInfo = nullptr,
|
||||||
|
});
|
||||||
|
shaderStages.emplace_back(vk::PipelineShaderStageCreateInfo {
|
||||||
|
.stage = vk::ShaderStageFlagBits::eFragment,
|
||||||
|
.module = fragShaderModule,
|
||||||
|
.pName = "main",
|
||||||
|
.pSpecializationInfo = &specI,
|
||||||
|
});
|
||||||
|
|
||||||
|
// custom rasterizationState with clockwise front face
|
||||||
|
vk::PipelineRasterizationStateCreateInfo rasterizationStateCI {
|
||||||
|
.depthClampEnable = VK_FALSE,
|
||||||
|
.rasterizerDiscardEnable = VK_FALSE,
|
||||||
|
.polygonMode = vk::PolygonMode::eFill,
|
||||||
|
.cullMode = vk::CullModeFlagBits::eBack,
|
||||||
|
.frontFace = vk::FrontFace::eClockwise,
|
||||||
|
.depthBiasEnable = VK_FALSE,
|
||||||
|
.lineWidth = 1.0f,
|
||||||
|
/* .depthBiasConstantFactor = 0.0f, */
|
||||||
|
/* .depthBiasClamp = 0.0f, */
|
||||||
|
/* .depthBiasSlopeFactor = 0.0f, */
|
||||||
|
};
|
||||||
|
vk::GraphicsPipelineCreateInfo pipelineCI {
|
||||||
|
.pRasterizationState = &rasterizationStateCI,
|
||||||
|
.renderPass = renderPass,
|
||||||
|
.subpass = 0,
|
||||||
|
};
|
||||||
|
pipelineCI.setStages(shaderStages);
|
||||||
|
|
||||||
|
std::vector<vk::PushConstantRange> pushConstantRanges;
|
||||||
|
pushConstantRanges.emplace_back(vk::PushConstantRange{
|
||||||
|
.stageFlags = vk::ShaderStageFlagBits::eFragment,
|
||||||
|
.size = sizeof(uint32_t),
|
||||||
|
});
|
||||||
|
vk.createGraphicsPipeline<Vertex3D>(std::move(pipelineCI), descriptorSetLayouts, pushConstantRanges, true, pipelines[R3Render]);
|
||||||
|
|
||||||
|
vk.getDevice().destroyShaderModule(vertShaderModule, nullptr);
|
||||||
|
vk.getDevice().destroyShaderModule(fragShaderModule, nullptr);
|
||||||
|
|
||||||
|
|
||||||
|
// BLIT TO SWAP CHAIN PIPELINE
|
||||||
|
/* auto fragShaderCode2 = readBinaryFile("shaders/blend.frag.spv"); */
|
||||||
|
/* vk::ShaderModule fragShaderModule2 = vk.createShaderModule(fragShaderCode); */
|
||||||
|
|
||||||
|
/* std::vector<vk::PipelineShaderStageCreateInfo> shaderStages2; */
|
||||||
|
/* shaderStages2.emplace_back(vk::PipelineShaderStageCreateInfo { */
|
||||||
|
/* .stage = vk::ShaderStageFlagBits::eFragment, */
|
||||||
|
/* .module = fragShaderModule2, */
|
||||||
|
/* .pName = "main", */
|
||||||
|
/* .pSpecializationInfo = nullptr, */
|
||||||
|
/* }); */
|
||||||
|
|
||||||
|
/* vk::GraphicsPipelineCreateInfo pipelineCI2 { */
|
||||||
|
/* .renderPass = renderPass, */
|
||||||
|
/* .subpass = 1, */
|
||||||
|
/* }; */
|
||||||
|
/* pipelineCI2.setStages(shaderStages2); */
|
||||||
|
|
||||||
|
/* vk.createGraphicsPipeline<Vertex3D>(std::move(pipelineCI2), nullptr, false, pipelines[blendToSC]); */
|
||||||
|
|
||||||
|
/* vk.getDevice().destroyShaderModule(fragShaderModule2, nullptr); */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// DESCRIPTORS
|
// DESCRIPTORS
|
||||||
//
|
//
|
||||||
void Renderer3D::createDescriptorResources() {
|
void Renderer3D::createDescriptorResources() {
|
||||||
rLog("createDescriptorResources: pool", reinterpret_cast<uint64_t>(static_cast<VkDescriptorPool>(descriptorPool)), "vs hpp:", reinterpret_cast<uint64_t>(&(*descriptorPool)));
|
|
||||||
// LAYOUTS
|
// LAYOUTS
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> uboDSLB;
|
std::vector<vk::DescriptorSetLayoutBinding> mvpDSLB;
|
||||||
// SET 1: uniform buffer object
|
// SET 1: uniform buffer object
|
||||||
uboDSLB.emplace_back(vk::DescriptorSetLayoutBinding {
|
mvpDSLB.emplace_back(vk::DescriptorSetLayoutBinding {
|
||||||
.binding = 0,
|
.binding = DS_MVP_BINDING,
|
||||||
.descriptorType = vk::DescriptorType::eUniformBuffer,
|
.descriptorType = vk::DescriptorType::eUniformBuffer,
|
||||||
.descriptorCount = 1,
|
.descriptorCount = 1,
|
||||||
.stageFlags = vk::ShaderStageFlagBits::eVertex,
|
.stageFlags = vk::ShaderStageFlagBits::eVertex,
|
||||||
/* .pImmutableSamplers = nullptr, */
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/* // SET 1: combined image sampler */
|
vk.createDescriptorSetLayout(mvpDSLB, mvpDSL);
|
||||||
/* set1bindings.emplace_back(vk::DescriptorSetLayoutBinding { */
|
|
||||||
/* .binding = 1, */
|
|
||||||
/* .descriptorType = vk::DescriptorType::eCombinedImageSampler, */
|
|
||||||
/* .descriptorCount = 1, */
|
|
||||||
/* .stageFlags = vk::ShaderStageFlagBits::eFragment, */
|
|
||||||
/* /1* .pImmutableSamplers = nullptr, *1/ */
|
|
||||||
/* }); */
|
|
||||||
vk.createDescriptorSetLayout(uboDSLB, uboDSL);
|
|
||||||
|
|
||||||
#ifndef RENDERER_3D_RENDER_TO_SWAP_CHAIN
|
#ifdef RENDERER_3D_ENABLE_SAMPLE_FROM_RENDER_IMAGES
|
||||||
// SET 2: combined image sampler
|
createDescriptorSetLayoutSampler(0);
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> sampleFromRenderImageDSLB;
|
|
||||||
sampleFromRenderImageDSLB.emplace_back(vk::DescriptorSetLayoutBinding {
|
|
||||||
.binding = 0,
|
|
||||||
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
|
||||||
.descriptorCount = 1,
|
|
||||||
.stageFlags = vk::ShaderStageFlagBits::eFragment,
|
|
||||||
});
|
|
||||||
vk.createDescriptorSetLayout(sampleFromRenderImageDSLB, sampleFromRenderImageDSL);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// POOL
|
// POOL
|
||||||
std::vector<vk::DescriptorPoolSize> poolSizes;
|
std::vector<vk::DescriptorPoolSize> poolSizes;
|
||||||
poolSizes = {
|
poolSizes = {
|
||||||
{ .type = vk::DescriptorType::eUniformBuffer, .descriptorCount = vk.getMaxFramesInFlight() },
|
{ .type = vk::DescriptorType::eUniformBuffer, .descriptorCount = vk.getMaxFramesInFlight() },
|
||||||
#ifndef RENDERER_3D_RENDER_TO_SWAP_CHAIN
|
#ifdef RENDERER_3D_ENABLE_SAMPLE_FROM_RENDER_IMAGES
|
||||||
{ .type = vk::DescriptorType::eCombinedImageSampler, .descriptorCount = vk.getMaxFramesInFlight() },
|
{ .type = vk::DescriptorType::eCombinedImageSampler, .descriptorCount = static_cast<uint32_t>(vk.getScImages().size()) },
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
vk.createDescriptorPool(poolSizes, vk.getMaxFramesInFlight(), descriptorPool);
|
uint32_t maxSets = 0;
|
||||||
|
for (auto& size : poolSizes) {
|
||||||
|
maxSets += size.descriptorCount;
|
||||||
|
}
|
||||||
|
vk.createDescriptorPool(poolSizes, maxSets, descriptorPool);
|
||||||
|
|
||||||
// SETS
|
rLog.log0("createDescriptorResources: Created descriptor layouts and pool");
|
||||||
// SET 1
|
}
|
||||||
std::vector<vk::DescriptorSetLayout> layouts1(vk.getMaxFramesInFlight(), uboDSL);
|
|
||||||
vk.createDescriptorSets(layouts1, descriptorPool, uboDS);
|
|
||||||
|
|
||||||
|
|
||||||
|
void Renderer3D::createDescriptorSetMvp() {
|
||||||
|
std::vector<vk::DescriptorSetLayout> layouts1(vk.getMaxFramesInFlight(), mvpDSL);
|
||||||
|
vk.createDescriptorSets(layouts1, descriptorPool, mvpDS);
|
||||||
|
|
||||||
|
assert(uniformBuffers.size() == vk.getMaxFramesInFlight());
|
||||||
|
assert(mvpDS.size() == vk.getMaxFramesInFlight());
|
||||||
for (size_t i = 0; i < vk.getMaxFramesInFlight(); i++) {
|
for (size_t i = 0; i < vk.getMaxFramesInFlight(); i++) {
|
||||||
vk::DescriptorBufferInfo bufferI {
|
vk::DescriptorBufferInfo bufferI {
|
||||||
.buffer = uniformBuffers[i],
|
.buffer = uniformBuffers[i],
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
.range = VK_WHOLE_SIZE, // sizeof(UniformBufferObject),
|
.range = VK_WHOLE_SIZE, // sizeof(ModelViewProjection),
|
||||||
};
|
};
|
||||||
|
|
||||||
vk::WriteDescriptorSet descriptorW{
|
vk::WriteDescriptorSet descriptorW{
|
||||||
.dstSet = uboDS[i],
|
.dstSet = mvpDS[i],
|
||||||
.dstBinding = 0,
|
.dstBinding = DS_MVP_BINDING,
|
||||||
.dstArrayElement = 0,
|
.dstArrayElement = 0,
|
||||||
.descriptorCount = 1,
|
.descriptorCount = 1,
|
||||||
.descriptorType = vk::DescriptorType::eUniformBuffer,
|
.descriptorType = vk::DescriptorType::eUniformBuffer,
|
||||||
@ -372,48 +445,23 @@ namespace gz::vlk {
|
|||||||
// write 1, copy 0
|
// write 1, copy 0
|
||||||
vk.getDevice().updateDescriptorSets(descriptorW, nullptr);
|
vk.getDevice().updateDescriptorSets(descriptorW, nullptr);
|
||||||
} // for
|
} // for
|
||||||
rLog.log0("createDescriptorResources: Created descriptor layout and sets for uniform buffer");
|
rLog.log0("createDescriptorSetMvp: Created", mvpDS.size(), "descriptor sets for model view projection");
|
||||||
|
|
||||||
#ifndef RENDERER_3D_RENDER_TO_SWAP_CHAIN
|
|
||||||
// SET 2:
|
|
||||||
std::vector<vk::DescriptorSetLayout> layouts2(vk.getMaxFramesInFlight(), sampleFromRenderImageDSL);
|
|
||||||
vk.createDescriptorSets(layouts2, descriptorPool, sampleFromRenderImageDS);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < vk.getMaxFramesInFlight(); i++) {
|
|
||||||
vk::DescriptorImageInfo imageI {
|
|
||||||
.sampler = imageSampler,
|
|
||||||
.imageView = renderImageViews[i],
|
|
||||||
.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
|
||||||
};
|
|
||||||
|
|
||||||
vk::WriteDescriptorSet descriptorW{
|
|
||||||
.dstSet = sampleFromRenderImageDS[i],
|
|
||||||
.dstBinding = 0,
|
|
||||||
.dstArrayElement = 0,
|
|
||||||
.descriptorCount = 1,
|
|
||||||
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
|
||||||
.pImageInfo = &imageI,
|
|
||||||
};
|
|
||||||
// write 1, copy 0
|
|
||||||
vk.getDevice().updateDescriptorSets(descriptorW, nullptr);
|
|
||||||
} // for
|
|
||||||
rLog.log0("createDescriptorResources: Created descriptor layout and sets for sampling from renderImages");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// MODEL
|
// MODEL
|
||||||
//
|
//
|
||||||
void Renderer3D::loadModel() {
|
void Renderer3D::loadModel() {
|
||||||
// load model into VerticesAndIndices struct
|
// load model into VerticesAndIndices struct
|
||||||
rLog.log1("Renderer3D: loadModel: loading model");
|
rLog.log1("Renderer3D: loadModel: loading model");
|
||||||
vk.loadModel(settings::MODEL_PATH, model);
|
/* vk.loadModel(settings::MODEL_PATH, model); */
|
||||||
// TODO use correct type
|
// TODO use correct type
|
||||||
vk::DeviceSize requiredVertexBufferSize = model.vertices.size() * sizeof(Vertex3D);
|
vk::DeviceSize requiredVertexBufferSize = model.vertices.size() * sizeof(Vertex3D);
|
||||||
vk::DeviceSize requiredIndexBufferSize = model.indices.size() * sizeof(uint32_t);
|
vk::DeviceSize requiredIndexBufferSize = model.indices.size() * sizeof(uint32_t);
|
||||||
|
|
||||||
if (requiredVertexBufferSize > vertexBufferSize) { throw VkException("Renderer3D::loadModel: vertex buffer too small"); }
|
if (requiredVertexBufferSize > vertexBufferSize) { throw VkException("Renderer3D::loadModel: vertex buffer too small, required size = " + gz::toString(requiredVertexBufferSize)); }
|
||||||
if (requiredIndexBufferSize > indexBufferSize) { throw VkException("Renderer3D::loadModel: index buffer too small"); }
|
if (requiredIndexBufferSize > indexBufferSize) { throw VkException("Renderer3D::loadModel: index buffer too small = " + gz::toString(requiredIndexBufferSize)); }
|
||||||
|
|
||||||
rLog.log0("Renderer3D: loadModel: filling vertex buffer");
|
rLog.log0("Renderer3D: loadModel: filling vertex buffer");
|
||||||
// copy to vertexBuffer
|
// copy to vertexBuffer
|
||||||
@ -486,8 +534,11 @@ namespace gz::vlk {
|
|||||||
commandBuffers[currentFrame].bindIndexBuffer(indexBuffer, NO_OFFSET, vk::IndexType::eUint32);
|
commandBuffers[currentFrame].bindIndexBuffer(indexBuffer, NO_OFFSET, vk::IndexType::eUint32);
|
||||||
|
|
||||||
uint32_t firstSet = 0;
|
uint32_t firstSet = 0;
|
||||||
std::vector<vk::DescriptorSet> descriptorSets = { uboDS[currentFrame], textureManager.getDescriptorSet() };
|
std::vector<vk::DescriptorSet> descriptorSets = { textureManager.getDescriptorSet(), mvpDS[currentFrame], };
|
||||||
commandBuffers[currentFrame].bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelines[R3Render].layout, firstSet, descriptorSets, {});
|
std::vector<uint32_t> dynamicOffsets;
|
||||||
|
commandBuffers[currentFrame].bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelines[R3Render].layout, firstSet, descriptorSets, dynamicOffsets);
|
||||||
|
/* commandBuffers[currentFrame].bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelines[R3Render].layout, firstSet, mvpDS[currentFrame], dynamicOffsets); */
|
||||||
|
/* commandBuffers[currentFrame].bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelines[R3Render].layout, firstSet, descriptorSets, dynamicOffsets); */
|
||||||
|
|
||||||
int instanceCount = 1;
|
int instanceCount = 1;
|
||||||
int firstIndex = 0;
|
int firstIndex = 0;
|
||||||
@ -500,7 +551,9 @@ namespace gz::vlk {
|
|||||||
/* commandBuffers[currentFrame].draw(6, 1, 0, 0); */
|
/* commandBuffers[currentFrame].draw(6, 1, 0, 0); */
|
||||||
commandBuffers[currentFrame].endRenderPass();
|
commandBuffers[currentFrame].endRenderPass();
|
||||||
|
|
||||||
|
#ifdef RENDERER_3D_COPY_TO_SWAP_CHAIN
|
||||||
vk.copyImageToImage(commandBuffers[currentFrame], renderImages[imageIndex], vk.getScImages()[imageIndex], vk.getScExtent());
|
vk.copyImageToImage(commandBuffers[currentFrame], renderImages[imageIndex], vk.getScImages()[imageIndex], vk.getScExtent());
|
||||||
|
#endif
|
||||||
result = commandBuffers[currentFrame].end();
|
result = commandBuffers[currentFrame].end();
|
||||||
if (result != vk::Result::eSuccess) {
|
if (result != vk::Result::eSuccess) {
|
||||||
rLog.error("Failed to record 3D - command buffer", "VkResult:", result);
|
rLog.error("Failed to record 3D - command buffer", "VkResult:", result);
|
||||||
@ -520,7 +573,7 @@ namespace gz::vlk {
|
|||||||
|
|
||||||
|
|
||||||
void Renderer3D::createUniformBuffers() {
|
void Renderer3D::createUniformBuffers() {
|
||||||
vk::DeviceSize bufferSize = sizeof(UniformBufferObject);
|
vk::DeviceSize bufferSize = sizeof(ModelViewProjection);
|
||||||
|
|
||||||
uniformBuffers.resize(vk.getMaxFramesInFlight());
|
uniformBuffers.resize(vk.getMaxFramesInFlight());
|
||||||
uniformBuffersMemory.resize(vk.getMaxFramesInFlight());
|
uniformBuffersMemory.resize(vk.getMaxFramesInFlight());
|
||||||
@ -537,21 +590,21 @@ namespace gz::vlk {
|
|||||||
float time = std::chrono::duration<float, std::chrono::seconds::period>(currentTime - startTime).count();
|
float time = std::chrono::duration<float, std::chrono::seconds::period>(currentTime - startTime).count();
|
||||||
|
|
||||||
// TODO use push constant instead of ubo
|
// TODO use push constant instead of ubo
|
||||||
UniformBufferObject ubo{};
|
ModelViewProjection mvp{};
|
||||||
ubo.model = glm::rotate(glm::mat4(1.0f), time * std::numbers::pi_v<float> / 2, glm::vec3(0.0f, 0.0f, 1.0f));
|
mvp.model = glm::rotate(glm::mat4(1.0f), time * std::numbers::pi_v<float> / 2, glm::vec3(0.0f, 0.0f, 1.0f));
|
||||||
ubo.view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f));
|
mvp.view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f));
|
||||||
ubo.projection = glm::perspective(glm::radians(45.0f), static_cast<float>(vk.getScExtent().width) / vk.getScExtent().height, 1.0f, 10.0f);
|
mvp.projection = glm::perspective(glm::radians(45.0f), static_cast<float>(vk.getScExtent().width) / vk.getScExtent().height, 1.0f, 10.0f);
|
||||||
/* ubo.model = glm::mat4(1); */
|
/* ubo.model = glm::mat4(1); */
|
||||||
/* ubo.view = glm::mat4(1); */
|
/* ubo.view = glm::mat4(1); */
|
||||||
/* ubo.projection = glm::mat4(1); */
|
/* ubo.projection = glm::mat4(1); */
|
||||||
/* ubo.projection[1][1] *= -1; // y coordinate inverted in opengl */
|
/* ubo.projection[1][1] *= -1; // y coordinate inverted in opengl */
|
||||||
MemoryInfo& uniformBufferMI = uniformBuffersMemory[vk.getCurrentFrame()];
|
MemoryInfo& uniformBufferMI = uniformBuffersMemory[vk.getCurrentFrame()];
|
||||||
void* data;
|
void* data;
|
||||||
vk::Result result = vk.getDevice().mapMemory(uniformBufferMI.memory, uniformBufferMI.offset, sizeof(ubo), NO_MEM_FLAGS, &data);
|
vk::Result result = vk.getDevice().mapMemory(uniformBufferMI.memory, uniformBufferMI.offset, sizeof(mvp), NO_MEM_FLAGS, &data);
|
||||||
if (result != vk::Result::eSuccess) {
|
if (result != vk::Result::eSuccess) {
|
||||||
throw getVkException(result, "Failed to map staging buffer", "Renderer3D::updateUniformBuffer");
|
throw getVkException(result, "Failed to map staging buffer", "Renderer3D::updateUniformBuffer");
|
||||||
}
|
}
|
||||||
memcpy(data, &ubo, sizeof(ubo));
|
memcpy(data, &mvp, sizeof(mvp));
|
||||||
vk.getDevice().unmapMemory(uniformBufferMI.memory);
|
vk.getDevice().unmapMemory(uniformBufferMI.memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include "vulkan_util.hpp"
|
#include "vulkan_util.hpp"
|
||||||
|
|
||||||
namespace gz::vlk {
|
namespace gz::vlk {
|
||||||
struct UniformBufferObject {
|
struct ModelViewProjection {
|
||||||
alignas(16) glm::mat4 model;
|
alignas(16) glm::mat4 model;
|
||||||
alignas(16) glm::mat4 view;
|
alignas(16) glm::mat4 view;
|
||||||
alignas(16) glm::mat4 projection;
|
alignas(16) glm::mat4 projection;
|
||||||
@ -16,6 +16,15 @@ namespace gz::vlk {
|
|||||||
R3Render,
|
R3Render,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 3D Renderer
|
||||||
|
* @details
|
||||||
|
* @section r3d_options Options
|
||||||
|
* - `RENDERER_3D_RENDER_TO_OWN_IMAGES`: render to own images
|
||||||
|
* - `RENDERER_3D_COPY_TO_SWAP_CHAIN`: copy the image to the swap chain after rendering it to the own image (swap chain images have to be created with TRANSFER_DST_BIT)
|
||||||
|
* - `RENDERER_3D_SAMPLE_FROM_RENDER_IMAGES`: enable sampling from the rendered images
|
||||||
|
* - `RENDERER_3D_RENDER_TO_SWAP_CHAIN`: render directly onto the swap chain
|
||||||
|
*/
|
||||||
class Renderer3D : public Renderer {
|
class Renderer3D : public Renderer {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@ -55,7 +64,8 @@ namespace gz::vlk {
|
|||||||
* Else:
|
* Else:
|
||||||
* - renderImages are images on renderImageMemory
|
* - renderImages are images on renderImageMemory
|
||||||
* - renderImageViews are views to renderImages
|
* - renderImageViews are views to renderImages
|
||||||
* - renderImageSampler is a combined image sampler
|
* - If `RENDERER_3D_ENABLE_SAMPLE_FROM_RENDER_IMAGES`
|
||||||
|
* - renderImageSampler is a combined image sampler
|
||||||
*/
|
*/
|
||||||
void createImageResources();
|
void createImageResources();
|
||||||
|
|
||||||
@ -87,7 +97,9 @@ namespace gz::vlk {
|
|||||||
* - initialLayout = vk::ImageLayout::eColorAttachmentOptimal
|
* - initialLayout = vk::ImageLayout::eColorAttachmentOptimal
|
||||||
* - finalLayout = vk::ImageLayout::eColorAttachmentOptimal
|
* - finalLayout = vk::ImageLayout::eColorAttachmentOptimal
|
||||||
* - stencil load/store = dont care
|
* - stencil load/store = dont care
|
||||||
|
*
|
||||||
* @subsection r3p_subpass2 Subpass 2: Blitting render image onto swap chain image
|
* @subsection r3p_subpass2 Subpass 2: Blitting render image onto swap chain image
|
||||||
|
* @todo remove
|
||||||
* Attributes:
|
* Attributes:
|
||||||
* - Pipeline: `Pipelines3D::blendToSC`
|
* - Pipeline: `Pipelines3D::blendToSC`
|
||||||
* - Descriptor layouts: `@ref r3p_desc2 "descriptorSet2Layout"`
|
* - Descriptor layouts: `@ref r3p_desc2 "descriptorSet2Layout"`
|
||||||
@ -110,6 +122,7 @@ namespace gz::vlk {
|
|||||||
std::vector<vk::Framebuffer> framebuffers;
|
std::vector<vk::Framebuffer> framebuffers;
|
||||||
// PIPELINE
|
// PIPELINE
|
||||||
PipelineContainer<Pipelines3D> pipelines;
|
PipelineContainer<Pipelines3D> pipelines;
|
||||||
|
void createPipelines();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name Desciptors
|
* @name Desciptors
|
||||||
@ -119,22 +132,28 @@ namespace gz::vlk {
|
|||||||
* Renderer3D has two descriptor sets, both allocated from the same pool.
|
* Renderer3D has two descriptor sets, both allocated from the same pool.
|
||||||
* @subsection r3d_desc1 Set 1: For rendering
|
* @subsection r3d_desc1 Set 1: For rendering
|
||||||
* Bindings:
|
* Bindings:
|
||||||
* -0. UniformBufferObject (DESCRIPTOR_TYPE_UNIFORM_BUFFER)
|
* -0. ModelViewProjection (DESCRIPTOR_TYPE_UNIFORM_BUFFER)
|
||||||
* @subsection r3d_desc2 Set 2: For sampling from the rendered image (only if not `RENDERER_3D_RENDER_TO_SWAP_CHAIN)
|
* @subsection r3d_desc2 Set 2: For sampling from the rendered image
|
||||||
|
* If `RENDERER_3D_ENABLE_SAMPLE_FROM_RENDER_IMAGES`:
|
||||||
* -0. Image sampler for current render image (DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
|
* -0. Image sampler for current render image (DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
|
||||||
*/
|
*/
|
||||||
/// @{
|
/// @{
|
||||||
vk::DescriptorPool descriptorPool;
|
vk::DescriptorSetLayout mvpDSL;
|
||||||
|
std::vector<vk::DescriptorSet> mvpDS;
|
||||||
vk::DescriptorSetLayout uboDSL;
|
|
||||||
std::vector<vk::DescriptorSet> uboDS;
|
|
||||||
|
|
||||||
vk::DescriptorSetLayout sampleFromRenderImageDSL;
|
|
||||||
std::vector<vk::DescriptorSet> sampleFromRenderImageDS;
|
|
||||||
/**
|
/**
|
||||||
* @brief Create @ref r3d_desc "all descritptor resources"
|
* @brief Create descriptor set layouts and pool
|
||||||
*/
|
*/
|
||||||
void createDescriptorResources();
|
void createDescriptorResources();
|
||||||
|
/**
|
||||||
|
* @brief Create @ref r3d_desc1 "model view projection descriptor sets"
|
||||||
|
*/
|
||||||
|
void createDescriptorSetMvp();
|
||||||
|
/**
|
||||||
|
* @brief Create @ref r3d_desc2 "sampler from render image descriptor sets"
|
||||||
|
* @details
|
||||||
|
* Swap chain dependant
|
||||||
|
*/
|
||||||
|
void createDescriptorSetSampler();
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -150,8 +169,9 @@ namespace gz::vlk {
|
|||||||
* @details
|
* @details
|
||||||
* Initializes:
|
* Initializes:
|
||||||
* - @ref createRenderPass() "render pass"
|
* - @ref createRenderPass() "render pass"
|
||||||
* - @ref createImages() "images and imageViews"
|
|
||||||
* - @ref createDepthImage() "depth image and view"
|
* - @ref createDepthImage() "depth image and view"
|
||||||
|
* - @ref createImageResources() "images and imageViews"
|
||||||
|
* - @ref createDescriptorSetSampler() "descriptors for sampling from render image"
|
||||||
* - @ref VulkanInstance::createFramebuffers() "framebuffers"
|
* - @ref VulkanInstance::createFramebuffers() "framebuffers"
|
||||||
* - pipelines:
|
* - pipelines:
|
||||||
* - R3Render
|
* - R3Render
|
||||||
@ -175,11 +195,12 @@ namespace gz::vlk {
|
|||||||
* -# destroy descriptor set layout and pool
|
* -# destroy descriptor set layout and pool
|
||||||
* -# call cleanupSwapChainDependantResources()
|
* -# call cleanupSwapChainDependantResources()
|
||||||
* -# call Renderer::cleanup_()
|
* -# call Renderer::cleanup_()
|
||||||
|
* -# destroy image sampler (if `RENDERER_3D_SAMPLE_FROM_RENDER_IMAGES`)
|
||||||
*/
|
*/
|
||||||
void cleanup();
|
void cleanup();
|
||||||
|
|
||||||
void loadModel();
|
void loadModel();
|
||||||
VerticesAndIndices<uint32_t> model;
|
VerticesAndIndices<Vertex3D, uint32_t> model;
|
||||||
|
|
||||||
Log rLog;
|
Log rLog;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user