feat: add forward+ rendering
This commit is contained in:
@@ -21,7 +21,8 @@ GameRenderer::GameRenderer()
|
||||
|
||||
void GameRenderer::init(GfxDevice& gfxDevice, RenderResources& _resources, glm::ivec2 drawImageSize)
|
||||
{
|
||||
try {
|
||||
try
|
||||
{
|
||||
resources = &_resources;
|
||||
sceneDataBuffer.init(
|
||||
gfxDevice,
|
||||
@@ -34,12 +35,15 @@ void GameRenderer::init(GfxDevice& gfxDevice, RenderResources& _resources, glm::
|
||||
meshPipeline = std::make_unique<MeshPipeline>();
|
||||
meshPipeline->init(gfxDevice, _resources, drawImageFormat, depthImageFormat);
|
||||
|
||||
skyboxPipeline = std::make_unique<SkyboxPipeline>();
|
||||
skyboxPipeline = std::make_unique<SkyboxPipeline>();
|
||||
skyboxPipeline->init(gfxDevice, _resources, drawImageFormat, depthImageFormat);
|
||||
|
||||
skinningPipeline = std::make_unique<SkinningPipeline>();
|
||||
skinningPipeline->init(gfxDevice);
|
||||
|
||||
lightCullingPipeline = std::make_unique<LightCullingPipeline>();
|
||||
lightCullingPipeline->init(gfxDevice, _resources, drawImageSize);
|
||||
|
||||
lineRenderingPass = std::make_unique<LineRenderingPass>();
|
||||
lineRenderingPass->init(gfxDevice, drawImageFormat);
|
||||
|
||||
@@ -48,7 +52,9 @@ skyboxPipeline = std::make_unique<SkyboxPipeline>();
|
||||
|
||||
GameState::GetInstance().SetRenderer(this);
|
||||
initialized = true;
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
cleanup(gfxDevice);
|
||||
throw;
|
||||
}
|
||||
@@ -59,6 +65,7 @@ void GameRenderer::beginDrawing(GfxDevice& gfxDevice)
|
||||
flushMaterialUpdates(gfxDevice);
|
||||
meshDrawCommands.clear();
|
||||
skinningPipeline->beginDrawing(gfxDevice.getCurrentFrameIndex());
|
||||
lightCullingPipeline->beginDrawing(gfxDevice.getCurrentFrameIndex());
|
||||
QuadRenderingManager::GetInstance().ClearQuads();
|
||||
}
|
||||
|
||||
@@ -70,13 +77,16 @@ void GameRenderer::endDrawing()
|
||||
std::stable_sort(
|
||||
sortedMeshDrawCommands.begin(),
|
||||
sortedMeshDrawCommands.end(),
|
||||
[this](std::size_t left, std::size_t right) {
|
||||
[this](std::size_t left, std::size_t right)
|
||||
{
|
||||
const auto& lhs = meshDrawCommands[left];
|
||||
const auto& rhs = meshDrawCommands[right];
|
||||
if (lhs.meshId != rhs.meshId) {
|
||||
if (lhs.meshId != rhs.meshId)
|
||||
{
|
||||
return lhs.meshId < rhs.meshId;
|
||||
}
|
||||
if (lhs.materialId != rhs.materialId) {
|
||||
if (lhs.materialId != rhs.materialId)
|
||||
{
|
||||
return lhs.materialId < rhs.materialId;
|
||||
}
|
||||
return (lhs.skinnedMesh != nullptr) < (rhs.skinnedMesh != nullptr);
|
||||
@@ -106,9 +116,17 @@ void GameRenderer::draw(VkCommandBuffer cmd, GfxDevice& gfxDevice, const Camera&
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
TracyVkZone(gfxDevice.getTracyVkCtx(), cmd, "Lights Buffer Flush");
|
||||
|
||||
lightCullingPipeline->flushCurrentFrame(cmd, gfxDevice);
|
||||
}
|
||||
|
||||
// TODO: there has to be a better way to do this
|
||||
const auto gpuSceneData = GPUSceneData{
|
||||
.view = sceneData.camera.GetViewMatrix(),
|
||||
.proj = sceneData.camera.GetProjectionMatrix(),
|
||||
.invProj = glm::inverse(sceneData.camera.GetProjectionMatrix()),
|
||||
.viewProj = sceneData.camera.GetViewProjectionMatrix(),
|
||||
.cameraPos = glm::vec4{sceneData.camera.m_position, 1.f},
|
||||
.ambientColor = {sceneData.ambientColor},
|
||||
@@ -116,6 +134,12 @@ void GameRenderer::draw(VkCommandBuffer cmd, GfxDevice& gfxDevice, const Camera&
|
||||
.fogColor = {sceneData.fogColor},
|
||||
.fogDensity = sceneData.fogDensity,
|
||||
.materialsBuffer = resources->materials().getMaterialDataBufferAddress(),
|
||||
.lightsBuffer = lightCullingPipeline->getLightsBufferAddress(),
|
||||
.tileLightIndicesBuffer = lightCullingPipeline->getTileLightIndicesBufferAddress(),
|
||||
.numLights = lightCullingPipeline->getNumLights(),
|
||||
.tileCountX = lightCullingPipeline->getTileCount().x,
|
||||
.debugLightHeatmap = renderLightHeatmap ? 1u : 0u,
|
||||
.padding = 0,
|
||||
};
|
||||
|
||||
{
|
||||
@@ -165,12 +189,60 @@ void GameRenderer::draw(VkCommandBuffer cmd, GfxDevice& gfxDevice, const Camera&
|
||||
depthImage.setLayout(VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL);
|
||||
}
|
||||
|
||||
{
|
||||
TracyVkZone(gfxDevice.getTracyVkCtx(), cmd, "Depth Prepass");
|
||||
|
||||
auto depthPrepassInfo = vkutil::createRenderingInfo({
|
||||
.renderExtent = drawImage.getExtent2D(),
|
||||
.depthImageView = depthImage.imageView,
|
||||
.depthImageClearValue = 1.f,
|
||||
});
|
||||
depthPrepassInfo.renderingInfo.pDepthAttachment = &depthPrepassInfo.depthAttachment;
|
||||
|
||||
vkCmdBeginRendering(cmd, &depthPrepassInfo.renderingInfo);
|
||||
|
||||
meshPipeline->drawDepthPrepass(
|
||||
cmd,
|
||||
drawImage.getExtent2D(),
|
||||
*resources,
|
||||
camera,
|
||||
sceneDataBuffer.getBuffer(),
|
||||
meshDrawCommands,
|
||||
sortedMeshDrawCommands);
|
||||
|
||||
vkCmdEndRendering(cmd);
|
||||
}
|
||||
|
||||
{
|
||||
TracyVkZone(gfxDevice.getTracyVkCtx(), cmd, "Light Culling");
|
||||
|
||||
vkutil::transitionImage(
|
||||
cmd,
|
||||
depthImage.image,
|
||||
depthImage.layout,
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
depthImage.setLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
|
||||
lightCullingPipeline->cullLights(
|
||||
cmd,
|
||||
*resources,
|
||||
sceneDataBuffer.getBuffer(),
|
||||
depthImageId,
|
||||
drawImage.getExtent2D());
|
||||
|
||||
vkutil::transitionImage(
|
||||
cmd,
|
||||
depthImage.image,
|
||||
depthImage.layout,
|
||||
VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL);
|
||||
depthImage.setLayout(VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL);
|
||||
}
|
||||
|
||||
auto renderInfo = vkutil::createRenderingInfo({
|
||||
.renderExtent = drawImage.getExtent2D(),
|
||||
.colorImageView = drawImage.imageView,
|
||||
.colorImageClearValue = glm::vec4{0.f, 0.f, 0.f, 1.f},
|
||||
.depthImageView = depthImage.imageView,
|
||||
.depthImageClearValue = 1.f,
|
||||
});
|
||||
renderInfo.renderingInfo.pColorAttachments = &renderInfo.colorAttachment;
|
||||
renderInfo.renderingInfo.pDepthAttachment = &renderInfo.depthAttachment;
|
||||
@@ -226,11 +298,11 @@ void GameRenderer::draw(VkCommandBuffer cmd, GfxDevice& gfxDevice, const Camera&
|
||||
*resources,
|
||||
drawImage,
|
||||
glm::ortho(0.0f,
|
||||
static_cast<float>(drawImage.extent.width),
|
||||
static_cast<float>(drawImage.extent.height),
|
||||
0.0f, -1.0f, 1.0f));
|
||||
static_cast<float>(drawImage.extent.width),
|
||||
static_cast<float>(drawImage.extent.height),
|
||||
0.0f, -1.0f, 1.0f));
|
||||
}
|
||||
// vkutil::cmdEndLabel(cmd);
|
||||
// vkutil::cmdEndLabel(cmd);
|
||||
}
|
||||
|
||||
void GameRenderer::drawQuads(
|
||||
@@ -246,11 +318,12 @@ void GameRenderer::cleanup(GfxDevice& gfxDevice)
|
||||
{
|
||||
VkDevice device = gfxDevice.getDevice();
|
||||
|
||||
if (device != VK_NULL_HANDLE) {
|
||||
if (device != VK_NULL_HANDLE)
|
||||
{
|
||||
vkDeviceWaitIdle(device);
|
||||
}
|
||||
|
||||
if (skinningPipeline)
|
||||
if (skinningPipeline)
|
||||
skinningPipeline->cleanup(gfxDevice);
|
||||
|
||||
if (lineRenderingPass)
|
||||
@@ -259,6 +332,9 @@ if (skinningPipeline)
|
||||
if (quadRendererPass)
|
||||
quadRendererPass->cleanup(gfxDevice);
|
||||
|
||||
if (lightCullingPipeline)
|
||||
lightCullingPipeline->cleanup(gfxDevice);
|
||||
|
||||
if (skyboxPipeline)
|
||||
skyboxPipeline->cleanup(device);
|
||||
|
||||
@@ -281,6 +357,7 @@ if (skinningPipeline)
|
||||
skinningPipeline.reset();
|
||||
lineRenderingPass.reset();
|
||||
quadRendererPass.reset();
|
||||
lightCullingPipeline.reset();
|
||||
pendingMaterialUploads.clear();
|
||||
meshDrawCommands.clear();
|
||||
sortedMeshDrawCommands.clear();
|
||||
@@ -323,6 +400,11 @@ void GameRenderer::drawSkinnedMesh(MeshID id,
|
||||
});
|
||||
}
|
||||
|
||||
void GameRenderer::submitLight(const Light& light)
|
||||
{
|
||||
lightCullingPipeline->appendLight(light);
|
||||
}
|
||||
|
||||
const GPUImage& GameRenderer::getDrawImage() const
|
||||
{
|
||||
assert(resources);
|
||||
@@ -349,7 +431,8 @@ void GameRenderer::setSkyboxTexture(ImageID skyboxImageId)
|
||||
|
||||
void GameRenderer::flushMaterialUpdates(GfxDevice& gfxDevice)
|
||||
{
|
||||
if (!pendingMaterialUploads.empty()) {
|
||||
if (!pendingMaterialUploads.empty())
|
||||
{
|
||||
// Material data is currently shared by all frame contexts. Wait before
|
||||
// mutating it so an older in-flight frame cannot read the overwritten
|
||||
// range. This can later be replaced with per-frame material buffers.
|
||||
|
||||
Reference in New Issue
Block a user