Added composite buffer render passes for deferred lighting path.

Refactoring KRCamera::renderFrame to use render passes.
Eliminate composite buffer binding GL code from KRCamera::renderFrame
This commit is contained in:
2022-07-04 22:08:05 -07:00
parent 17113b59ea
commit 68c3831fde
6 changed files with 90 additions and 90 deletions

View File

@@ -100,7 +100,7 @@ const std::string KRCamera::getSkyBox() const
return m_skyBox;
}
void KRCamera::renderFrame(VkCommandBuffer& commandBuffer, KRSurface& surface)
void KRCamera::renderFrame(VkCommandBuffer& commandBuffer, KRSurface& compositeSurface)
{
// ----====---- Record timing information for measuring FPS ----====----
uint64_t current_time = m_pContext->getAbsoluteTimeMilliseconds();
@@ -110,7 +110,7 @@ void KRCamera::renderFrame(VkCommandBuffer& commandBuffer, KRSurface& surface)
}
m_last_frame_start = current_time;
createBuffers(surface.getWidth(), surface.getHeight());
createBuffers(compositeSurface.getWidth(), compositeSurface.getHeight());
KRScene &scene = getScene();
@@ -119,7 +119,7 @@ void KRCamera::renderFrame(VkCommandBuffer& commandBuffer, KRSurface& surface)
//Matrix4 viewMatrix = Matrix4::Invert(getModelMatrix());
settings.setViewportSize(Vector2::Create((float)surface.getWidth(), (float)surface.getHeight()));
settings.setViewportSize(Vector2::Create((float)compositeSurface.getWidth(), (float)compositeSurface.getHeight()));
Matrix4 projectionMatrix{};
projectionMatrix.perspective(settings.perspective_fov, settings.m_viewportSize.x / settings.m_viewportSize.y, settings.perspective_nearz, settings.perspective_farz);
m_viewport = KRViewport(settings.getViewportSize(), viewMatrix, projectionMatrix);
@@ -131,13 +131,13 @@ void KRCamera::renderFrame(VkCommandBuffer& commandBuffer, KRSurface& surface)
scene.updateOctree(m_viewport);
// ----====---- Pre-stream resources ----====----
scene.render(commandBuffer, surface, this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_PRESTREAM, true);
scene.render(commandBuffer, compositeSurface, this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_PRESTREAM, true);
// ----====---- Generate Shadowmaps for Lights ----====----
if(settings.m_cShadowBuffers > 0) {
GL_PUSH_GROUP_MARKER("Generate Shadowmaps");
scene.render(commandBuffer, surface, this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_GENERATE_SHADOWMAPS, false /*settings.bEnableDeferredLighting*/);
scene.render(commandBuffer, compositeSurface, this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_GENERATE_SHADOWMAPS, false /*settings.bEnableDeferredLighting*/);
GLDEBUG(glViewport(0, 0, (GLsizei)m_viewport.getSize().x, (GLsizei)m_viewport.getSize().y));
GL_POP_GROUP_MARKER;
}
@@ -148,14 +148,15 @@ void KRCamera::renderFrame(VkCommandBuffer& commandBuffer, KRSurface& surface)
GL_PUSH_GROUP_MARKER("Deferred Lighting - Pass 1 (Opaque)");
// Set render target
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, compositeFramebuffer));
GLDEBUG(glClearColor(0.0f, 0.0f, 0.0f, 0.0f));
GLDEBUG(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
// Start render pass
KRRenderPass& deferredGBufferPass = compositeSurface.getDeferredGBufferPass();
deferredGBufferPass.begin(commandBuffer, compositeSurface, Vector4::Zero());
// Render the geometry
scene.render(commandBuffer, surface, this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_DEFERRED_GBUFFER, false);
scene.render(commandBuffer, compositeSurface, this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_DEFERRED_GBUFFER, false);
// End render pass
deferredGBufferPass.end(commandBuffer);
GL_POP_GROUP_MARKER;
@@ -177,31 +178,27 @@ void KRCamera::renderFrame(VkCommandBuffer& commandBuffer, KRSurface& surface)
m_pContext->getTextureManager()->selectTexture(GL_TEXTURE_2D, 7, compositeDepthTexture);
// Render the geometry
scene.render(commandBuffer, surface, this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_DEFERRED_LIGHTS, false);
scene.render(commandBuffer, compositeSurface, this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_DEFERRED_LIGHTS, false);
GL_POP_GROUP_MARKER;
// ----====---- Opaque Geometry, Deferred rendering Pass 3 ----====----
GL_PUSH_GROUP_MARKER("Deferred Lighting - Pass 3 (Opaque)");
// Set render target
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, compositeFramebuffer));
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, compositeDepthTexture, 0));
GLDEBUG(glClearColor(0.0f, 0.0f, 0.0f, 1.0f));
GLDEBUG(glClear(GL_COLOR_BUFFER_BIT));
// Start render pass
KRRenderPass& deferredOpaquePass = compositeSurface.getDeferredOpaquePass();
deferredOpaquePass.begin(commandBuffer, compositeSurface, Vector4::Create(0.0f, 0.0f, 0.0f, 1.0f));
// Set source to buffers from pass 2
m_pContext->getTextureManager()->selectTexture(GL_TEXTURE_2D, 6, lightAccumulationTexture);
// Render the geometry
// TODO: At this point, we only want to render octree nodes that produced fragments during the 1st pass into the GBuffer
scene.render(commandBuffer, surface, this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_DEFERRED_OPAQUE, false);
scene.render(commandBuffer, compositeSurface, this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_DEFERRED_OPAQUE, false);
// Deactivate source buffer texture units
m_pContext->getTextureManager()->selectTexture(GL_TEXTURE_2D, 6, 0);
m_pContext->getTextureManager()->selectTexture(GL_TEXTURE_2D, 7, 0);
// End render pass
deferredOpaquePass.end(commandBuffer);
GL_POP_GROUP_MARKER;
} else {
@@ -209,21 +206,15 @@ void KRCamera::renderFrame(VkCommandBuffer& commandBuffer, KRSurface& surface)
GL_PUSH_GROUP_MARKER("Forward Rendering - Opaque");
/*
// Set render target
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, compositeFramebuffer));
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, compositeDepthTexture, 0));
GLDEBUG(glViewport(0, 0, (GLsizei)(m_viewport.getSize().x * m_downsample.x), (GLsizei)(m_viewport.getSize().y * m_downsample.y)));
GLDEBUG(glClearColor(0.0f, 0.0f, 0.0f, 1.0f));
GLDEBUG(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
*/
KRRenderPass& forwardOpaquePass = surface.getForwardOpaquePass();
forwardOpaquePass.begin(commandBuffer, surface);
// Start render pass
KRRenderPass& forwardOpaquePass = compositeSurface.getForwardOpaquePass();
forwardOpaquePass.begin(commandBuffer, compositeSurface, Vector4::Create(0.0f, 0.0f, 0.0f, 1.0f));
// Render the geometry
scene.render(commandBuffer, surface, this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_FORWARD_OPAQUE, false);
scene.render(commandBuffer, compositeSurface, this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_FORWARD_OPAQUE, false);
GL_POP_GROUP_MARKER;
@@ -238,7 +229,7 @@ void KRCamera::renderFrame(VkCommandBuffer& commandBuffer, KRSurface& surface)
info.pCamera = this;
info.renderPass = KRNode::RENDER_PASS_FORWARD_TRANSPARENT;
info.rasterMode = PipelineInfo::RasterMode::kAlphaBlend;
KRPipeline* testPipeline = m_pContext->getPipelineManager()->getPipeline(surface, info, testVertices.getVertexAttributes(), KRMesh::model_format_t::KRENGINE_MODEL_FORMAT_STRIP);
KRPipeline* testPipeline = m_pContext->getPipelineManager()->getPipeline(compositeSurface, info, testVertices.getVertexAttributes(), KRMesh::model_format_t::KRENGINE_MODEL_FORMAT_STRIP);
testPipeline->bind(commandBuffer);
testVertices.bind(commandBuffer);
vkCmdDraw(commandBuffer, 4, 1, 0, 0);
@@ -253,14 +244,6 @@ void KRCamera::renderFrame(VkCommandBuffer& commandBuffer, KRSurface& surface)
// ----====---- Sky Box ----====----
GL_PUSH_GROUP_MARKER("Sky Box");
// TODO - Vulkan refactoring...
/*
// Set render target
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, compositeFramebuffer));
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, compositeDepthTexture, 0));
*/
if(!m_pSkyBoxTexture && m_skyBox.length()) {
m_pSkyBoxTexture = getContext().getTextureManager()->getTextureCube(m_skyBox.c_str());
@@ -276,8 +259,8 @@ void KRCamera::renderFrame(VkCommandBuffer& commandBuffer, KRSurface& surface)
info.rasterMode = PipelineInfo::RasterMode::kOpaqueNoDepthWrite;
info.cullMode = PipelineInfo::CullMode::kCullNone;
KRPipeline* pPipeline = getContext().getPipelineManager()->getPipeline(surface, info);
getContext().getPipelineManager()->selectPipeline(surface, *this, pPipeline, m_viewport, Matrix4(), nullptr, nullptr, nullptr, 0, KRNode::RENDER_PASS_FORWARD_OPAQUE, Vector3::Zero(), 0.0f, Vector4::Zero());
KRPipeline* pPipeline = getContext().getPipelineManager()->getPipeline(compositeSurface, info);
getContext().getPipelineManager()->selectPipeline(compositeSurface, *this, pPipeline, m_viewport, Matrix4(), nullptr, nullptr, nullptr, 0, KRNode::RENDER_PASS_FORWARD_OPAQUE, Vector3::Zero(), 0.0f, Vector4::Zero());
getContext().getTextureManager()->selectTexture(0, m_pSkyBoxTexture, 0.0f, KRTexture::TEXTURE_USAGE_SKY_CUBE);
@@ -291,48 +274,28 @@ void KRCamera::renderFrame(VkCommandBuffer& commandBuffer, KRSurface& surface)
// ----====---- Transparent Geometry, Forward Rendering ----====----
// TODO - Vulkan refactoring...
GL_PUSH_GROUP_MARKER("Forward Rendering - Transparent");
/*
// Note: These parameters have already been set up by the skybox render above
//
// // Set render target
// GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, compositeFramebuffer));
// GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, compositeDepthTexture, 0));
*/
// Render all transparent geometry
scene.render(commandBuffer, surface, this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_FORWARD_TRANSPARENT, false);
scene.render(commandBuffer, compositeSurface, this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_FORWARD_TRANSPARENT, false);
GL_POP_GROUP_MARKER;
// ----====---- Particle Occlusion Tests ----====----
GL_PUSH_GROUP_MARKER("Particle Occlusion Tests");
/*
// Set render target
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, compositeFramebuffer));
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, compositeDepthTexture, 0));
*/
// ----====---- Perform Occlusion Tests ----====----
scene.render(commandBuffer, surface, this, m_viewport.getVisibleBounds(), m_viewport, RENDER_PASS_PARTICLE_OCCLUSION, false);
scene.render(commandBuffer, compositeSurface, this, m_viewport.getVisibleBounds(), m_viewport, RENDER_PASS_PARTICLE_OCCLUSION, false);
GL_POP_GROUP_MARKER;
// ----====---- Flares ----====----
GL_PUSH_GROUP_MARKER("Additive Particles");
/*
// Set render target
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, compositeFramebuffer));
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, compositeDepthTexture, 0));
*/
// Render all flares
scene.render(commandBuffer, surface, this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_ADDITIVE_PARTICLES, false);
scene.render(commandBuffer, compositeSurface, this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_ADDITIVE_PARTICLES, false);
GL_POP_GROUP_MARKER;
@@ -362,15 +325,7 @@ void KRCamera::renderFrame(VkCommandBuffer& commandBuffer, KRSurface& surface)
GLDEBUG(glDepthRangef(0.0, 1.0));
}
scene.render(commandBuffer, surface, this, m_viewport.getVisibleBounds(), volumetricLightingViewport, KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE, false);
if(settings.volumetric_environment_downsample != 0) {
// Set render target
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, compositeFramebuffer));
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, compositeDepthTexture, 0));
GLDEBUG(glViewport(0, 0, (GLsizei)m_viewport.getSize().x, (GLsizei)m_viewport.getSize().y));
}
scene.render(commandBuffer, compositeSurface, this, m_viewport.getVisibleBounds(), volumetricLightingViewport, KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE, false);
GL_POP_GROUP_MARKER;
}
@@ -379,7 +334,6 @@ void KRCamera::renderFrame(VkCommandBuffer& commandBuffer, KRSurface& surface)
// ----====---- Debug Overlay ----====----
// TODO - Vulkan refactoring...
GL_PUSH_GROUP_MARKER("Debug Overlays");
if(settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_OCTREE) {
@@ -389,14 +343,14 @@ void KRCamera::renderFrame(VkCommandBuffer& commandBuffer, KRSurface& surface)
info.pCamera = this;
info.renderPass = KRNode::RENDER_PASS_FORWARD_TRANSPARENT;
info.rasterMode = PipelineInfo::RasterMode::kAdditive;
KRPipeline *pVisShader = getContext().getPipelineManager()->getPipeline(surface, info);
KRPipeline *pVisShader = getContext().getPipelineManager()->getPipeline(compositeSurface, info);
m_pContext->getMeshManager()->bindVBO(commandBuffer, &getContext().getMeshManager()->KRENGINE_VBO_DATA_3D_CUBE_VERTICES, 1.0f);
for(unordered_map<AABB, int>::iterator itr=m_viewport.getVisibleBounds().begin(); itr != m_viewport.getVisibleBounds().end(); itr++) {
Matrix4 matModel = Matrix4();
matModel.scale((*itr).first.size() * 0.5f);
matModel.translate((*itr).first.center());
if(getContext().getPipelineManager()->selectPipeline(surface, *this, pVisShader, m_viewport, matModel, nullptr, nullptr, nullptr, 0, KRNode::RENDER_PASS_FORWARD_TRANSPARENT, Vector3::Zero(), 0.0f, Vector4::Zero())) {
if(getContext().getPipelineManager()->selectPipeline(compositeSurface, *this, pVisShader, m_viewport, matModel, nullptr, nullptr, nullptr, 0, KRNode::RENDER_PASS_FORWARD_TRANSPARENT, Vector3::Zero(), 0.0f, Vector4::Zero())) {
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 14));
}
}
@@ -411,7 +365,7 @@ void KRCamera::renderFrame(VkCommandBuffer& commandBuffer, KRSurface& surface)
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO));
renderPost(commandBuffer, surface); // FINDME! Re-enable with Vulkan refactoring
renderPost(commandBuffer, compositeSurface); // FINDME! Re-enable with Vulkan refactoring
*/
GL_POP_GROUP_MARKER;

View File

@@ -54,7 +54,7 @@ public:
KRCamera(KRScene &scene, std::string name);
virtual ~KRCamera();
void renderFrame(VkCommandBuffer& commandBuffer, KRSurface& surface);
void renderFrame(VkCommandBuffer& commandBuffer, KRSurface& compositeSurface);
KRRenderSettings settings;

View File

@@ -45,7 +45,7 @@ KRRenderPass::~KRRenderPass()
assert(m_renderPass == VK_NULL_HANDLE);
}
void KRRenderPass::create(KRDevice &device, VkFormat swapChainImageFormat, VkFormat depthImageFormat)
void KRRenderPass::create(KRDevice &device, VkFormat swapChainImageFormat, VkFormat depthImageFormat, const RenderPassInfo& info)
{
if (m_renderPass) {
return;
@@ -65,8 +65,8 @@ void KRRenderPass::create(KRDevice &device, VkFormat swapChainImageFormat, VkFor
VkAttachmentDescription depthAttachment{};
depthAttachment.format = depthImageFormat;
depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depthAttachment.loadOp = info.clearDepth ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
depthAttachment.storeOp = info.keepDepth ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE;
depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
@@ -118,10 +118,13 @@ void KRRenderPass::destroy(KRDevice &device)
}
}
void KRRenderPass::begin(VkCommandBuffer& commandBuffer, KRSurface& surface)
void KRRenderPass::begin(VkCommandBuffer& commandBuffer, KRSurface& surface, const Vector4& clearColor)
{
std::array<VkClearValue, 2> clearValues{};
clearValues[0].color = { {0.0f, 0.0f, 0.0f, 1.0f} };
clearValues[0].color.float32[0] = clearColor[0];
clearValues[0].color.float32[1] = clearColor[1];
clearValues[0].color.float32[2] = clearColor[2];
clearValues[0].color.float32[3] = clearColor[3];
clearValues[1].depthStencil = { 1.0f, 0 };
VkRenderPassBeginInfo renderPassInfo{};

View File

@@ -42,10 +42,17 @@ class KRRenderPass : public KRContextObject
public:
KRRenderPass(KRContext& context);
~KRRenderPass();
void create(KRDevice& device, VkFormat swapChainImageFormat, VkFormat depthImageFormat);
struct RenderPassInfo
{
bool clearDepth;
bool keepDepth;
};
void create(KRDevice& device, VkFormat swapChainImageFormat, VkFormat depthImageFormat, const RenderPassInfo& info);
void destroy(KRDevice& device);
void begin(VkCommandBuffer &commandBuffer, KRSurface& surface);
void begin(VkCommandBuffer &commandBuffer, KRSurface& surface, const Vector4& clearColor);
void end(VkCommandBuffer& commandBuffer);
// private:

View File

@@ -49,6 +49,8 @@ KRSurface::KRSurface(KRContext& context)
, m_frameIndex(0)
{
m_forwardOpaquePass = std::make_unique<KRRenderPass>(context);
m_deferredGBufferPass = std::make_unique<KRRenderPass>(context);
m_deferredOpaquePass = std::make_unique<KRRenderPass>(context);
m_swapChain = std::make_unique<KRSwapchain>(context);
}
@@ -96,6 +98,14 @@ void KRSurface::destroy()
m_forwardOpaquePass->destroy(*device);
}
if (m_deferredGBufferPass) {
m_deferredGBufferPass->destroy(*device);
}
if (m_deferredOpaquePass) {
m_deferredOpaquePass->destroy(*device);
}
if (device && m_renderFinishedSemaphore != VK_NULL_HANDLE) {
vkDestroySemaphore(device->m_logicalDevice, m_renderFinishedSemaphore, nullptr);
m_renderFinishedSemaphore = VK_NULL_HANDLE;
@@ -147,7 +157,19 @@ KrResult KRSurface::createSwapChain()
}
m_forwardOpaquePass->create(*device, selectedSurfaceFormat.format, depthImageFormat);
KRRenderPass::RenderPassInfo info{};
info.clearDepth = true;
info.keepDepth = false;
m_forwardOpaquePass->create(*device, selectedSurfaceFormat.format, depthImageFormat, info);
info.clearDepth = true;
info.keepDepth = true;
m_deferredGBufferPass->create(*device, selectedSurfaceFormat.format, depthImageFormat, info);
info.clearDepth = false;
info.keepDepth = false;
m_deferredOpaquePass->create(*device, selectedSurfaceFormat.format, depthImageFormat, info);
m_swapChain->create(*device, m_surface, selectedSurfaceFormat, depthImageFormat, swapExtent, imageCount, *m_forwardOpaquePass);
return KR_SUCCESS;
@@ -196,12 +218,21 @@ VkFormat KRSurface::getDepthFormat() const
return m_swapChain->m_depthFormat;
}
KRRenderPass& KRSurface::getForwardOpaquePass()
{
return *m_forwardOpaquePass;
}
KRRenderPass& KRSurface::getDeferredGBufferPass()
{
return *m_deferredGBufferPass;
}
KRRenderPass& KRSurface::getDeferredOpaquePass()
{
return *m_deferredOpaquePass;
}
void KRSurface::endFrame()
{
m_frameIndex++;;

View File

@@ -61,6 +61,9 @@ public:
KrResult recreateSwapChain();
KRRenderPass& getForwardOpaquePass();
KRRenderPass& getDeferredGBufferPass();
KRRenderPass& getDeferredOpaquePass();
void endFrame();
#ifdef WIN32
@@ -74,6 +77,8 @@ public:
std::unique_ptr<KRSwapchain> m_swapChain;
std::unique_ptr<KRRenderPass> m_forwardOpaquePass;
std::unique_ptr<KRRenderPass> m_deferredGBufferPass;
std::unique_ptr<KRRenderPass> m_deferredOpaquePass;
// TODO - This needs to be advanced per swap chain
uint64_t m_frameIndex;