ADD: SSR
This commit is contained in:
208
src/render/passes/ssr.cpp
Normal file
208
src/render/passes/ssr.cpp
Normal file
@@ -0,0 +1,208 @@
|
||||
#include "ssr.h"
|
||||
|
||||
#include "core/frame/resources.h"
|
||||
#include "core/descriptor/manager.h"
|
||||
#include "core/descriptor/descriptors.h"
|
||||
#include "core/device/device.h"
|
||||
#include "core/device/resource.h"
|
||||
#include "core/device/swapchain.h"
|
||||
#include "core/context.h"
|
||||
#include "core/pipeline/manager.h"
|
||||
#include "core/assets/manager.h"
|
||||
#include "core/pipeline/sampler.h"
|
||||
|
||||
#include "render/graph/graph.h"
|
||||
#include "render/pipelines.h"
|
||||
|
||||
void SSRPass::init(EngineContext *context)
|
||||
{
|
||||
_context = context;
|
||||
if (!_context || !_context->getDevice() || !_context->getDescriptorLayouts() || !_context->pipelines)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
VkDevice device = _context->getDevice()->device();
|
||||
|
||||
// Set 1 layout: HDR + G-Buffer inputs (all sampled images).
|
||||
{
|
||||
DescriptorLayoutBuilder builder;
|
||||
builder.add_binding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); // hdrColor
|
||||
builder.add_binding(1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); // posTex
|
||||
builder.add_binding(2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); // normalTex
|
||||
builder.add_binding(3, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); // albedoTex
|
||||
_inputSetLayout = builder.build(
|
||||
device,
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
nullptr,
|
||||
VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT);
|
||||
}
|
||||
|
||||
// Graphics pipeline: fullscreen triangle, no depth, HDR color attachment.
|
||||
GraphicsPipelineCreateInfo info{};
|
||||
info.vertexShaderPath = _context->getAssets()->shaderPath("fullscreen.vert.spv");
|
||||
info.fragmentShaderPath = _context->getAssets()->shaderPath("ssr.frag.spv");
|
||||
info.setLayouts = {
|
||||
_context->getDescriptorLayouts()->gpuSceneDataLayout(), // set = 0 (sceneData UBO)
|
||||
_inputSetLayout // set = 1 (HDR + GBuffer)
|
||||
};
|
||||
|
||||
info.configure = [this](PipelineBuilder &b)
|
||||
{
|
||||
b.set_input_topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
|
||||
b.set_polygon_mode(VK_POLYGON_MODE_FILL);
|
||||
b.set_cull_mode(VK_CULL_MODE_NONE, VK_FRONT_FACE_CLOCKWISE);
|
||||
b.set_multisampling_none();
|
||||
b.disable_depthtest();
|
||||
b.disable_blending();
|
||||
if (_context && _context->getSwapchain())
|
||||
{
|
||||
b.set_color_attachment_format(_context->getSwapchain()->drawImage().imageFormat);
|
||||
}
|
||||
};
|
||||
|
||||
_context->pipelines->createGraphicsPipeline("ssr", info);
|
||||
}
|
||||
|
||||
void SSRPass::cleanup()
|
||||
{
|
||||
if (_context && _context->getDevice() && _inputSetLayout)
|
||||
{
|
||||
vkDestroyDescriptorSetLayout(_context->getDevice()->device(), _inputSetLayout, nullptr);
|
||||
_inputSetLayout = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
_deletionQueue.flush();
|
||||
}
|
||||
|
||||
void SSRPass::execute(VkCommandBuffer)
|
||||
{
|
||||
// Executed via render graph; nothing to do here.
|
||||
}
|
||||
|
||||
void SSRPass::register_graph(RenderGraph *graph,
|
||||
RGImageHandle hdrInput,
|
||||
RGImageHandle gbufPos,
|
||||
RGImageHandle gbufNorm,
|
||||
RGImageHandle gbufAlbedo,
|
||||
RGImageHandle hdrOutput)
|
||||
{
|
||||
if (!graph || !hdrInput.valid() || !hdrOutput.valid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
graph->add_pass(
|
||||
"SSR",
|
||||
RGPassType::Graphics,
|
||||
[hdrInput, gbufPos, gbufNorm, gbufAlbedo, hdrOutput](RGPassBuilder &builder, EngineContext *)
|
||||
{
|
||||
// Read current HDR lighting + G-Buffer; write to an HDR output.
|
||||
builder.read(hdrInput, RGImageUsage::SampledFragment);
|
||||
if (gbufPos.valid())
|
||||
{
|
||||
builder.read(gbufPos, RGImageUsage::SampledFragment);
|
||||
}
|
||||
if (gbufNorm.valid())
|
||||
{
|
||||
builder.read(gbufNorm, RGImageUsage::SampledFragment);
|
||||
}
|
||||
if (gbufAlbedo.valid())
|
||||
{
|
||||
builder.read(gbufAlbedo, RGImageUsage::SampledFragment);
|
||||
}
|
||||
builder.write_color(hdrOutput, false /*load existing contents*/);
|
||||
},
|
||||
[this, hdrInput, gbufPos, gbufNorm, gbufAlbedo](VkCommandBuffer cmd,
|
||||
const RGPassResources &res,
|
||||
EngineContext *ctx)
|
||||
{
|
||||
draw_ssr(cmd, ctx, res, hdrInput, gbufPos, gbufNorm, gbufAlbedo);
|
||||
});
|
||||
}
|
||||
|
||||
void SSRPass::draw_ssr(VkCommandBuffer cmd,
|
||||
EngineContext *context,
|
||||
const RGPassResources &resources,
|
||||
RGImageHandle hdrInput,
|
||||
RGImageHandle gbufPos,
|
||||
RGImageHandle gbufNorm,
|
||||
RGImageHandle gbufAlbedo)
|
||||
{
|
||||
EngineContext *ctxLocal = context ? context : _context;
|
||||
if (!ctxLocal || !ctxLocal->currentFrame) return;
|
||||
|
||||
ResourceManager *resourceManager = ctxLocal->getResources();
|
||||
DeviceManager *deviceManager = ctxLocal->getDevice();
|
||||
DescriptorManager *descriptorLayouts = ctxLocal->getDescriptorLayouts();
|
||||
PipelineManager *pipelineManager = ctxLocal->pipelines;
|
||||
if (!resourceManager || !deviceManager || !descriptorLayouts || !pipelineManager) return;
|
||||
|
||||
VkImageView hdrView = resources.image_view(hdrInput);
|
||||
VkImageView posView = resources.image_view(gbufPos);
|
||||
VkImageView normView = resources.image_view(gbufNorm);
|
||||
VkImageView albedoView = resources.image_view(gbufAlbedo);
|
||||
if (hdrView == VK_NULL_HANDLE || posView == VK_NULL_HANDLE ||
|
||||
normView == VK_NULL_HANDLE || albedoView == VK_NULL_HANDLE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch (or refresh) pipeline for hot-reload support.
|
||||
if (!pipelineManager->getGraphics("ssr", _pipeline, _pipelineLayout))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Scene UBO (set=0, binding=0) – mirror LightingPass behavior.
|
||||
AllocatedBuffer sceneBuf = resourceManager->create_buffer(
|
||||
sizeof(GPUSceneData),
|
||||
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
||||
VMA_MEMORY_USAGE_CPU_TO_GPU);
|
||||
ctxLocal->currentFrame->_deletionQueue.push_function([resourceManager, sceneBuf]()
|
||||
{
|
||||
resourceManager->destroy_buffer(sceneBuf);
|
||||
});
|
||||
|
||||
VmaAllocationInfo allocInfo{};
|
||||
vmaGetAllocationInfo(deviceManager->allocator(), sceneBuf.allocation, &allocInfo);
|
||||
auto *sceneUniformData = static_cast<GPUSceneData *>(allocInfo.pMappedData);
|
||||
*sceneUniformData = ctxLocal->getSceneData();
|
||||
vmaFlushAllocation(deviceManager->allocator(), sceneBuf.allocation, 0, sizeof(GPUSceneData));
|
||||
|
||||
VkDescriptorSet globalSet = ctxLocal->currentFrame->_frameDescriptors.allocate(
|
||||
deviceManager->device(), descriptorLayouts->gpuSceneDataLayout());
|
||||
{
|
||||
DescriptorWriter writer;
|
||||
writer.write_buffer(0, sceneBuf.buffer, sizeof(GPUSceneData), 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
|
||||
writer.update_set(deviceManager->device(), globalSet);
|
||||
}
|
||||
|
||||
// Input set (set=1): HDR color + G-Buffer textures.
|
||||
VkDescriptorSet inputSet = ctxLocal->currentFrame->_frameDescriptors.allocate(
|
||||
deviceManager->device(), _inputSetLayout);
|
||||
{
|
||||
DescriptorWriter writer;
|
||||
writer.write_image(0, hdrView, ctxLocal->getSamplers()->defaultLinear(),
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
|
||||
writer.write_image(1, posView, ctxLocal->getSamplers()->defaultLinear(),
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
|
||||
writer.write_image(2, normView, ctxLocal->getSamplers()->defaultLinear(),
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
|
||||
writer.write_image(3, albedoView, ctxLocal->getSamplers()->defaultLinear(),
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
|
||||
writer.update_set(deviceManager->device(), inputSet);
|
||||
}
|
||||
|
||||
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, _pipeline);
|
||||
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, _pipelineLayout, 0, 1, &globalSet, 0, nullptr);
|
||||
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, _pipelineLayout, 1, 1, &inputSet, 0, nullptr);
|
||||
|
||||
VkExtent2D extent = ctxLocal->getDrawExtent();
|
||||
VkViewport vp{0.f, 0.f, (float)extent.width, (float)extent.height, 0.f, 1.f};
|
||||
VkRect2D sc{{0, 0}, extent};
|
||||
vkCmdSetViewport(cmd, 0, 1, &vp);
|
||||
vkCmdSetScissor(cmd, 0, 1, &sc);
|
||||
|
||||
vkCmdDraw(cmd, 3, 1, 0, 0);
|
||||
}
|
||||
49
src/render/passes/ssr.h
Normal file
49
src/render/passes/ssr.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#include "render/renderpass.h"
|
||||
#include "render/graph/types.h"
|
||||
|
||||
class RenderGraph;
|
||||
class RGPassResources;
|
||||
|
||||
// Screen Space Reflections (SSR) pass.
|
||||
// In v1 this is a lightweight stub wired into the RenderGraph by the engine.
|
||||
// The full pipeline and shader implementation is added in later plan steps.
|
||||
class SSRPass : public IRenderPass
|
||||
{
|
||||
public:
|
||||
void init(EngineContext *context) override;
|
||||
void cleanup() override;
|
||||
void execute(VkCommandBuffer cmd) override;
|
||||
|
||||
const char *getName() const override { return "SSR"; }
|
||||
|
||||
// Register SSR in the render graph.
|
||||
// hdrInput : HDR color buffer produced by deferred lighting.
|
||||
// gbufPos : G-Buffer world-space position (RGBA32F).
|
||||
// gbufNorm : G-Buffer world-space normal + roughness.
|
||||
// gbufAlbedo : G-Buffer albedo + metallic.
|
||||
// hdrOutput : HDR color buffer that will carry lighting + SSR.
|
||||
void register_graph(RenderGraph *graph,
|
||||
RGImageHandle hdrInput,
|
||||
RGImageHandle gbufPos,
|
||||
RGImageHandle gbufNorm,
|
||||
RGImageHandle gbufAlbedo,
|
||||
RGImageHandle hdrOutput);
|
||||
|
||||
private:
|
||||
EngineContext *_context = nullptr;
|
||||
VkDescriptorSetLayout _inputSetLayout = VK_NULL_HANDLE; // set=1: HDR + GBuffer inputs
|
||||
VkPipeline _pipeline = VK_NULL_HANDLE;
|
||||
VkPipelineLayout _pipelineLayout = VK_NULL_HANDLE;
|
||||
|
||||
void draw_ssr(VkCommandBuffer cmd,
|
||||
EngineContext *context,
|
||||
const class RGPassResources &resources,
|
||||
RGImageHandle hdrInput,
|
||||
RGImageHandle gbufPos,
|
||||
RGImageHandle gbufNorm,
|
||||
RGImageHandle gbufAlbedo);
|
||||
|
||||
DeletionQueue _deletionQueue;
|
||||
};
|
||||
Reference in New Issue
Block a user