From e6706a4e1f3cec5e2e463140fabbf41c9b57d6fa Mon Sep 17 00:00:00 2001 From: Kearwood Gilbert Date: Sun, 14 Jan 2024 15:36:51 -0800 Subject: [PATCH] Now rendering black frames rather than empty frames when scene isn't loaded, preventing some Vulkan validation errors. Added keepColor, clearColor, and finalLayout attributes to KRRenderPass::RenderPassInfo. Now able to render debug text on macOS. --- kraken/KRCamera.cpp | 136 +++++++++++++++++++------------- kraken/KRCamera.h | 1 + kraken/KRPresentationThread.cpp | 2 + kraken/KRRenderPass.cpp | 12 ++- kraken/KRRenderPass.h | 3 + kraken/KRSurface.cpp | 69 +++++++++++++++- kraken/KRSurface.h | 8 ++ 7 files changed, 170 insertions(+), 61 deletions(-) diff --git a/kraken/KRCamera.cpp b/kraken/KRCamera.cpp index b36b782..50a757a 100755 --- a/kraken/KRCamera.cpp +++ b/kraken/KRCamera.cpp @@ -404,10 +404,23 @@ void KRCamera::renderFrame(VkCommandBuffer& commandBuffer, KRSurface& compositeS // fprintf(stderr, "VBO Mem: %i Kbyte Texture Mem: %i/%i Kbyte (active/total) Shader Handles: %i Visible Bounds: %i Max Texture LOD: %i\n", (int)m_pContext->getMeshManager()->getMemUsed() / 1024, (int)m_pContext->getTextureManager()->getActiveMemUsed() / 1024, (int)m_pContext->getTextureManager()->getMemUsed() / 1024, (int)m_pContext->getPipelineManager()->getShaderHandlesUsed(), (int)m_visibleBounds.size(), m_pContext->getTextureManager()->getLODDimCap()); + GL_PUSH_GROUP_MARKER("Debug Overlays"); + + renderDebug(commandBuffer, compositeSurface); + + + GL_POP_GROUP_MARKER; + GL_PUSH_GROUP_MARKER("Post Processing"); + KRRenderPass& postCompositePass = compositeSurface.getPostCompositePass(); + postCompositePass.begin(commandBuffer, compositeSurface, Vector4::Create(0.0f, 0.0f, 0.0f, 1.0f)); + renderPost(commandBuffer, compositeSurface); + postCompositePass.end(commandBuffer); + + GL_POP_GROUP_MARKER; } @@ -573,62 +586,67 @@ void KRCamera::destroyBuffers() void KRCamera::renderPost(VkCommandBuffer& commandBuffer, KRSurface& surface) { /* - // TODO - Re-enable once post fx shader is converted for Vulkan - KRMeshManager::KRVBOData& vertices = getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES; + // TODO - Re-enable once post fx shader is converted for Vulkan + KRMeshManager::KRVBOData& vertices = getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES; + + PipelineInfo info{}; + std::string shader_name("PostShader"); + info.shader_name = &shader_name; + info.pCamera = this; + info.renderPass = KRNode::RENDER_PASS_FORWARD_TRANSPARENT; + info.rasterMode = RasterMode::kOpaqueNoTest; + info.modelFormat = ModelFormat::KRENGINE_MODEL_FORMAT_STRIP; + info.vertexAttributes = vertices.getVertexAttributes(); + + KRPipeline *postShader = m_pContext->getPipelineManager()->getPipeline(surface, info); + + postShader->setPushConstant(KRPipeline::PushConstant::fade_color, m_fade_color); + postShader->bind(commandBuffer, *this, m_viewport, Matrix4(), nullptr, nullptr, nullptr, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); + + m_pContext->getTextureManager()->selectTexture(GL_TEXTURE_2D, 0, compositeDepthTexture); + m_pContext->getTextureManager()->selectTexture(GL_TEXTURE_2D, 1, compositeColorTexture); + + if(settings.volumetric_environment_enable) { + m_pContext->getTextureManager()->selectTexture(GL_TEXTURE_2D, 2, volumetricLightAccumulationTexture); + } + + // Update attribute values. + m_pContext->getMeshManager()->bindVBO(commandBuffer, &vertices, 1.0f); + + vkCmdDraw(commandBuffer, 4, 1, 0, 0); + */ + + + // if(bShowShadowBuffer) { + // KRPipeline *blitShader = m_pContext->getPipelineManager()->getShader("simple_blit", this, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); + // + // for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) { + // Matrix4 viewMatrix = Matrix4(); + // viewMatrix.scale(0.20, 0.20, 0.20); + // viewMatrix.translate(-0.70, 0.70 - 0.45 * iShadow, 0.0); + // getContext().getPipelineManager()->selectShader(blitShader, KRViewport(getViewportSize(), viewMatrix, Matrix4()), shadowViewports, Matrix4(), Vector3(), NULL, 0, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); + // m_pContext->getTextureManager()->selectTexture(1, NULL); + // m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES); + // m_pContext->getTextureManager()->_setActiveTexture(0); + // GLDEBUG(glBindTexture(GL_TEXTURE_2D, shadowDepthTexture[iShadow])); + //#if GL_EXT_shadow_samplers + // GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_EXT, GL_NONE)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available + //#endif + // GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); + //#if GL_EXT_shadow_samplers + // GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_EXT, GL_COMPARE_REF_TO_TEXTURE_EXT)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available + //#endif + // } + // + // m_pContext->getTextureManager()->selectTexture(0, NULL); + // m_pContext->getTextureManager()->_setActiveTexture(0); + // GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0)); + // } + +} - PipelineInfo info{}; - std::string shader_name("PostShader"); - info.shader_name = &shader_name; - info.pCamera = this; - info.renderPass = KRNode::RENDER_PASS_FORWARD_TRANSPARENT; - info.rasterMode = RasterMode::kOpaqueNoTest; - info.modelFormat = ModelFormat::KRENGINE_MODEL_FORMAT_STRIP; - info.vertexAttributes = vertices.getVertexAttributes(); - - KRPipeline *postShader = m_pContext->getPipelineManager()->getPipeline(surface, info); - - postShader->setPushConstant(KRPipeline::PushConstant::fade_color, m_fade_color); - postShader->bind(commandBuffer, *this, m_viewport, Matrix4(), nullptr, nullptr, nullptr, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); - - m_pContext->getTextureManager()->selectTexture(GL_TEXTURE_2D, 0, compositeDepthTexture); - m_pContext->getTextureManager()->selectTexture(GL_TEXTURE_2D, 1, compositeColorTexture); - - if(settings.volumetric_environment_enable) { - m_pContext->getTextureManager()->selectTexture(GL_TEXTURE_2D, 2, volumetricLightAccumulationTexture); - } - - // Update attribute values. - m_pContext->getMeshManager()->bindVBO(commandBuffer, &vertices, 1.0f); - - vkCmdDraw(commandBuffer, 4, 1, 0, 0); - */ - - - // if(bShowShadowBuffer) { - // KRPipeline *blitShader = m_pContext->getPipelineManager()->getShader("simple_blit", this, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); - // - // for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) { - // Matrix4 viewMatrix = Matrix4(); - // viewMatrix.scale(0.20, 0.20, 0.20); - // viewMatrix.translate(-0.70, 0.70 - 0.45 * iShadow, 0.0); - // getContext().getPipelineManager()->selectShader(blitShader, KRViewport(getViewportSize(), viewMatrix, Matrix4()), shadowViewports, Matrix4(), Vector3(), NULL, 0, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); - // m_pContext->getTextureManager()->selectTexture(1, NULL); - // m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES); - // m_pContext->getTextureManager()->_setActiveTexture(0); - // GLDEBUG(glBindTexture(GL_TEXTURE_2D, shadowDepthTexture[iShadow])); - //#if GL_EXT_shadow_samplers - // GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_EXT, GL_NONE)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available - //#endif - // GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); - //#if GL_EXT_shadow_samplers - // GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_EXT, GL_COMPARE_REF_TO_TEXTURE_EXT)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available - //#endif - // } - // - // m_pContext->getTextureManager()->selectTexture(0, NULL); - // m_pContext->getTextureManager()->_setActiveTexture(0); - // GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0)); - // } +void KRCamera::renderDebug(VkCommandBuffer& commandBuffer, KRSurface& surface) +{ const char* szText = settings.m_debug_text.c_str(); std::string debug_text; @@ -755,6 +773,11 @@ void KRCamera::renderPost(VkCommandBuffer& commandBuffer, KRSurface& surface) iCol++; } } + + m_debug_text_vbo_data.load(commandBuffer); + + KRRenderPass& debugPass = surface.getDebugPass(); + debugPass.begin(commandBuffer, surface, Vector4::Create(0.0f, 0.0f, 0.0f, 1.0f)); KRTexture* fontTexture = m_pContext->getTextureManager()->getTexture("font"); fontTexture->resetPoolExpiry(0.0f, KRTexture::TEXTURE_USAGE_UI); @@ -772,10 +795,11 @@ void KRCamera::renderPost(VkCommandBuffer& commandBuffer, KRSurface& surface) fontShader->setImageBinding("fontTexture", fontTexture, getContext().getSamplerManager()->DEFAULT_CLAMPED_SAMPLER); fontShader->bind(commandBuffer, *this, m_viewport, Matrix4(), nullptr, nullptr, nullptr, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); - m_debug_text_vbo_data.load(commandBuffer); m_debug_text_vbo_data.bind(commandBuffer); vkCmdDraw(commandBuffer, vertex_count, 1, 0, 0); + + debugPass.end(commandBuffer); m_debug_text_vertices.unlock(); diff --git a/kraken/KRCamera.h b/kraken/KRCamera.h index 30eb909..70c9f7a 100755 --- a/kraken/KRCamera.h +++ b/kraken/KRCamera.h @@ -90,6 +90,7 @@ private: int volumetricLightAccumulationBuffer, volumetricLightAccumulationTexture; void renderPost(VkCommandBuffer& commandBuffer, KRSurface& surface); + void renderDebug(VkCommandBuffer& commandBuffer, KRSurface& surface); void destroyBuffers(); diff --git a/kraken/KRPresentationThread.cpp b/kraken/KRPresentationThread.cpp index 3d25c5f..d8fb801 100644 --- a/kraken/KRPresentationThread.cpp +++ b/kraken/KRPresentationThread.cpp @@ -162,6 +162,8 @@ void KRPresentationThread::renderFrame() float deltaTime = 0.005; // TODO - Replace dummy value if (scene) { scene->renderFrame(commandBuffer, surface, deltaTime); + } else { + surface.renderBlackFrame(commandBuffer); } if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) { diff --git a/kraken/KRRenderPass.cpp b/kraken/KRRenderPass.cpp index 96c8224..a0133af 100644 --- a/kraken/KRRenderPass.cpp +++ b/kraken/KRRenderPass.cpp @@ -56,12 +56,16 @@ void KRRenderPass::create(KRDevice& device, VkFormat swapChainImageFormat, VkFor VkAttachmentDescription colorAttachment{}; colorAttachment.format = swapChainImageFormat; colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT; - colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + colorAttachment.loadOp = info.clearColor ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD; + colorAttachment.storeOp = info.keepColor ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE; 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; + colorAttachment.initialLayout = info.clearColor ? VK_IMAGE_LAYOUT_UNDEFINED : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + if (info.finalPass) { + colorAttachment.finalLayout = info.keepColor ? VK_IMAGE_LAYOUT_PRESENT_SRC_KHR : VK_IMAGE_LAYOUT_UNDEFINED; + } else { + colorAttachment.finalLayout = info.keepColor ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED; + } VkAttachmentDescription depthAttachment{}; diff --git a/kraken/KRRenderPass.h b/kraken/KRRenderPass.h index f2a7ca1..ed851f3 100644 --- a/kraken/KRRenderPass.h +++ b/kraken/KRRenderPass.h @@ -44,8 +44,11 @@ public: struct RenderPassInfo { + bool clearColor; + bool keepColor; bool clearDepth; bool keepDepth; + bool finalPass; }; void create(KRDevice& device, VkFormat swapChainImageFormat, VkFormat depthImageFormat, const RenderPassInfo& info); diff --git a/kraken/KRSurface.cpp b/kraken/KRSurface.cpp index 7eaa7f3..529541c 100644 --- a/kraken/KRSurface.cpp +++ b/kraken/KRSurface.cpp @@ -49,6 +49,9 @@ KRSurface::KRSurface(KRContext& context, KrSurfaceHandle handle, void* platformH m_forwardOpaquePass = std::make_unique(context); m_deferredGBufferPass = std::make_unique(context); m_deferredOpaquePass = std::make_unique(context); + m_postCompositePass = std::make_unique(context); + m_debugPass = std::make_unique(context); + m_blackFramePass = std::make_unique(context); m_swapChain = std::make_unique(context); } @@ -124,6 +127,18 @@ void KRSurface::destroy() if (m_deferredOpaquePass) { m_deferredOpaquePass->destroy(*device); } + + if (m_postCompositePass) { + m_postCompositePass->destroy(*device); + } + + if (m_debugPass) { + m_debugPass->destroy(*device); + } + + if (m_blackFramePass) { + m_blackFramePass->destroy(*device); + } for (int i=0; i < KRENGINE_MAX_FRAMES_IN_FLIGHT; i++) { if (device && m_renderFinishedSemaphores[i] != VK_NULL_HANDLE) { @@ -184,17 +199,47 @@ KrResult KRSurface::createSwapChain() KRRenderPass::RenderPassInfo info{}; + info.clearColor = true; + info.keepColor = true; info.clearDepth = true; info.keepDepth = false; + info.finalPass = false; m_forwardOpaquePass->create(*device, selectedSurfaceFormat.format, depthImageFormat, info); + info.clearColor = true; + info.keepColor = true; info.clearDepth = true; info.keepDepth = true; + info.finalPass = false; m_deferredGBufferPass->create(*device, selectedSurfaceFormat.format, depthImageFormat, info); + info.clearColor = false; + info.keepColor = true; + info.clearDepth = false; + info.keepDepth = true; + info.finalPass = false; + m_deferredOpaquePass->create(*device, selectedSurfaceFormat.format, depthImageFormat, info); + + info.clearColor = false; + info.keepColor = true; + info.clearDepth = false; + info.keepDepth = true; + info.finalPass = false; + m_debugPass->create(*device, selectedSurfaceFormat.format, depthImageFormat, info); + + info.clearColor = false; + info.keepColor = true; info.clearDepth = false; info.keepDepth = false; - m_deferredOpaquePass->create(*device, selectedSurfaceFormat.format, depthImageFormat, info); + info.finalPass = true; + m_postCompositePass->create(*device, selectedSurfaceFormat.format, depthImageFormat, info); + + info.clearColor = true; + info.keepColor = true; + info.clearDepth = false; + info.keepDepth = false; + info.finalPass = true; + m_blackFramePass->create(*device, selectedSurfaceFormat.format, depthImageFormat, info); m_swapChain->create(*device, m_surface, selectedSurfaceFormat, depthImageFormat, swapExtent, imageCount, *m_forwardOpaquePass); @@ -264,7 +309,29 @@ KRRenderPass& KRSurface::getDeferredOpaquePass() return *m_deferredOpaquePass; } +KRRenderPass& KRSurface::getPostCompositePass() +{ + return *m_postCompositePass; +} + +KRRenderPass& KRSurface::getDebugPass() +{ + return *m_debugPass; +} + +KRRenderPass& KRSurface::getBlackFramePass() +{ + return *m_blackFramePass; +} + void KRSurface::endFrame() { m_frameIndex++;; } + + +void KRSurface::renderBlackFrame(VkCommandBuffer &commandBuffer) +{ + m_blackFramePass->begin(commandBuffer, *this, Vector4::Create(0.0f, 0.0f, 0.0f, 1.0f)); + m_blackFramePass->end(commandBuffer); +} diff --git a/kraken/KRSurface.h b/kraken/KRSurface.h index 83ddce0..7581b1d 100644 --- a/kraken/KRSurface.h +++ b/kraken/KRSurface.h @@ -48,6 +48,7 @@ public: uint32_t getHeight() const; hydra::Vector2i getDimensions() const; VkFormat getDepthFormat() const; + void renderBlackFrame(VkCommandBuffer &commandBuffer); KRSurface(const KRSurface&) = delete; KRSurface& operator=(const KRSurface&) = delete; @@ -59,6 +60,9 @@ public: KRRenderPass& getDeferredGBufferPass(); KRRenderPass& getDeferredOpaquePass(); + KRRenderPass& getPostCompositePass(); + KRRenderPass& getDebugPass(); + KRRenderPass& getBlackFramePass(); void endFrame(); KrSurfaceHandle m_handle; @@ -75,6 +79,10 @@ public: std::unique_ptr m_forwardOpaquePass; std::unique_ptr m_deferredGBufferPass; std::unique_ptr m_deferredOpaquePass; + std::unique_ptr m_postCompositePass; + std::unique_ptr m_debugPass; + std::unique_ptr m_blackFramePass; + // TODO - This needs to be advanced per swap chain uint64_t m_frameIndex;