From 3c948e2337f901056d0372337649743b06c2f26a Mon Sep 17 00:00:00 2001 From: Kearwood Gilbert Date: Sun, 27 Feb 2022 22:10:17 -0800 Subject: [PATCH] WIP Vulkan Refactoring and reflection driven vertex attribute binding --- kraken/KRPipelineManager.cpp | 32 ++++++---- kraken/KRPresentationThread.cpp | 5 +- kraken/KRSurface.cpp | 80 ++++++++++++++++++++++-- kraken/KRSurface.h | 9 +++ standard_assets/shaders/vulkan_test.vert | 3 + 5 files changed, 111 insertions(+), 18 deletions(-) diff --git a/kraken/KRPipelineManager.cpp b/kraken/KRPipelineManager.cpp index c467324..28b1b95 100644 --- a/kraken/KRPipelineManager.cpp +++ b/kraken/KRPipelineManager.cpp @@ -62,21 +62,29 @@ KRPipelineManager::~KRPipelineManager() { #endif // ANDROID } -void KRPipelineManager::createPipelines(KRSurface& surface) +KRPipeline* KRPipelineManager::getPipeline(KRSurface& surface, const std::string& shader_name, uint32_t vertexAttributes) { - { - // vulkan_test - std::string pipeline_name = "vulkan_test"; - std::vector shaders; - shaders.push_back(m_pContext->getShaderManager()->get(pipeline_name + ".vert", "spv")); - shaders.push_back(m_pContext->getShaderManager()->get(pipeline_name + ".frag", "spv")); - KRPipeline* pipeline = new KRPipeline(*m_pContext, surface.m_deviceHandle, surface.m_swapChainImageFormat, surface.m_swapChainExtent.width, surface.m_swapChainExtent.height , pipeline_name.c_str(), shaders); - std::pair > key; - key.first = pipeline_name; - m_pipelines[key] = pipeline; + std::pair > key; + key.first = shader_name; + key.second.push_back(surface.m_deviceHandle); + key.second.push_back(surface.m_swapChainImageFormat); + key.second.push_back(surface.m_swapChainExtent.width); + key.second.push_back(surface.m_swapChainExtent.height); + key.second.push_back(vertexAttributes); + PipelineMap::iterator itr = m_pipelines.find(key); + if (itr != m_pipelines.end()) { + return itr->second; } -} + std::vector shaders; + shaders.push_back(m_pContext->getShaderManager()->get(shader_name + ".vert", "spv")); + shaders.push_back(m_pContext->getShaderManager()->get(shader_name + ".frag", "spv")); + KRPipeline* pipeline = new KRPipeline(*m_pContext, surface, shader_name.c_str(), shaders, vertexAttributes); + + m_pipelines[key] = pipeline; + + return pipeline; +} KRPipeline *KRPipelineManager::getPipeline(const std::string &pipeline_name, KRCamera *pCamera, const std::vector &point_lights, const std::vector &directional_lights, const std::vector&spot_lights, int bone_count, bool bDiffuseMap, bool bNormalMap, bool bSpecMap, bool bReflectionMap, bool bReflectionCubeMap, bool bLightMap, bool bDiffuseMapScale,bool bSpecMapScale, bool bNormalMapScale, bool bReflectionMapScale, bool bDiffuseMapOffset, bool bSpecMapOffset, bool bNormalMapOffset, bool bReflectionMapOffset, bool bAlphaTest, bool bAlphaBlend, KRNode::RenderPass renderPass, bool bRimColor) { diff --git a/kraken/KRPresentationThread.cpp b/kraken/KRPresentationThread.cpp index 214107b..c10d8a9 100644 --- a/kraken/KRPresentationThread.cpp +++ b/kraken/KRPresentationThread.cpp @@ -139,11 +139,12 @@ void KRPresentationThread::renderFrame() // TODO - this will break with more than one surface... Expect to refactor this out VkCommandBuffer commandBuffer = device.m_graphicsCommandBuffers[imageIndex]; - KRPipeline* testPipeline = m_pContext->getPipelineManager()->get("vulkan_test"); KRMeshManager::KRVBOData& testVertices = getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES; bool haveMesh = testVertices.isVBOReady(); + KRPipeline* testPipeline = m_pContext->getPipelineManager()->getPipeline(surface, "vulkan_test", testVertices.getVertexAttributes()); + VkCommandBufferBeginInfo beginInfo{}; beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; beginInfo.flags = 0; @@ -158,7 +159,7 @@ void KRPresentationThread::renderFrame() VkRenderPassBeginInfo renderPassInfo{}; renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - renderPassInfo.renderPass = testPipeline->getRenderPass(); + renderPassInfo.renderPass = surface.getRenderPass(); renderPassInfo.framebuffer = surface.m_swapChainFramebuffers[frameIndex % surface.m_swapChainFramebuffers.size()]; renderPassInfo.renderArea.offset = { 0, 0 }; renderPassInfo.renderArea.extent = surface.m_swapChainExtent; diff --git a/kraken/KRSurface.cpp b/kraken/KRSurface.cpp index 290ad2f..6d3d6bf 100644 --- a/kraken/KRSurface.cpp +++ b/kraken/KRSurface.cpp @@ -47,6 +47,7 @@ KRSurface::KRSurface(KRContext& context) , m_swapChainExtent({ 0, 0 }) , m_imageAvailableSemaphore(VK_NULL_HANDLE) , m_renderFinishedSemaphore(VK_NULL_HANDLE) + , m_renderPass(VK_NULL_HANDLE) { } @@ -90,6 +91,11 @@ void KRSurface::destroy() destroySwapChain(); std::unique_ptr& device = m_pContext->getDeviceManager()->getDevice(m_deviceHandle); + + if (m_renderPass) { + vkDestroyRenderPass(device->m_logicalDevice, m_renderPass, nullptr); + m_renderPass = VK_NULL_HANDLE; + } if (device && m_renderFinishedSemaphore != VK_NULL_HANDLE) { vkDestroySemaphore(device->m_logicalDevice, m_renderFinishedSemaphore, nullptr); @@ -230,10 +236,8 @@ KrResult KRSurface::createSwapChain() } } - KRPipelineManager* pipelineManager = m_pContext->getPipelineManager(); - pipelineManager->createPipelines(*this); + createRenderPasses(); - KRPipeline* testPipeline = pipelineManager->get("vulkan_test"); m_swapChainFramebuffers.resize(m_swapChainImageViews.size()); for (size_t i = 0; i < m_swapChainImageViews.size(); i++) { @@ -241,7 +245,7 @@ KrResult KRSurface::createSwapChain() VkFramebufferCreateInfo framebufferInfo{}; framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - framebufferInfo.renderPass = testPipeline->getRenderPass(); + framebufferInfo.renderPass = getRenderPass(); framebufferInfo.attachmentCount = 1; framebufferInfo.pAttachments = attachments; framebufferInfo.width = m_swapChainExtent.width; @@ -291,3 +295,71 @@ KrResult KRSurface::recreateSwapChain() return result; } +void KRSurface::createRenderPasses() +{ + if (m_renderPass) { + return; + } + + VkAttachmentDescription colorAttachment{}; + colorAttachment.format = m_swapChainImageFormat; + 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.attachment = 0; + colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkSubpassDescription subpass{}; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &colorAttachmentRef; + + VkSubpassDependency dependency{}; + dependency.srcSubpass = VK_SUBPASS_EXTERNAL; + dependency.dstSubpass = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.srcAccessMask = 0; + dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + + VkRenderPassCreateInfo renderPassInfo{}; + renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + renderPassInfo.attachmentCount = 1; + renderPassInfo.pAttachments = &colorAttachment; + renderPassInfo.subpassCount = 1; + renderPassInfo.pSubpasses = &subpass; + renderPassInfo.dependencyCount = 1; + renderPassInfo.pDependencies = &dependency; + + std::unique_ptr& device = m_pContext->getDeviceManager()->getDevice(m_deviceHandle); + + if (vkCreateRenderPass(device->m_logicalDevice, &renderPassInfo, nullptr, &m_renderPass) != VK_SUCCESS) { + // failed! TODO - Error handling + } +} + +VkRenderPass& KRSurface::getRenderPass() +{ + return m_renderPass; +} + +std::unique_ptr& KRSurface::getDevice() +{ + return m_pContext->getDeviceManager()->getDevice(m_deviceHandle); +} + +uint32_t KRSurface::getWidth() const +{ + return m_swapChainExtent.width; +} + +uint32_t KRSurface::getHeight() const +{ + return m_swapChainExtent.height; +} diff --git a/kraken/KRSurface.h b/kraken/KRSurface.h index 06d94be..766324f 100644 --- a/kraken/KRSurface.h +++ b/kraken/KRSurface.h @@ -35,6 +35,8 @@ #ifndef KRSURFACE_H #define KRSURFACE_H +class KRDevice; + class KRSurface : public KRContextObject { public: @@ -45,12 +47,17 @@ public: #endif ~KRSurface(); void destroy(); + uint32_t getWidth() const; + uint32_t getHeight() const; KRSurface(const KRSurface&) = delete; KRSurface& operator=(const KRSurface&) = delete; + std::unique_ptr& getDevice(); KrResult initialize(); KrResult recreateSwapChain(); + void createRenderPasses(); + VkRenderPass& getRenderPass(); #ifdef WIN32 HWND m_hWnd; @@ -66,6 +73,8 @@ public: VkSemaphore m_imageAvailableSemaphore; VkSemaphore m_renderFinishedSemaphore; + // TODO - Move this to a higher context + VkRenderPass m_renderPass; private: void destroySwapChain(); diff --git a/standard_assets/shaders/vulkan_test.vert b/standard_assets/shaders/vulkan_test.vert index 56ec6dc..3158429 100644 --- a/standard_assets/shaders/vulkan_test.vert +++ b/standard_assets/shaders/vulkan_test.vert @@ -4,6 +4,9 @@ // See https://vulkan-tutorial.com/Drawing_a_triangle/Graphics_pipeline_basics/Shader_modules layout(location = 0) out vec3 fragColor; +layout(location = 0) in vec3 vertex_position; +layout(location = 1) in vec3 vertex_uv; +layout(constant_id = 0) const int QUALITY_LEVEL = 64; // Specialization constant test vec2 positions[3] = vec2[]( vec2(0.0, -0.5),