ssr.cpp

cross platform rendering playground

src/passes/ssr/ssr.cpp

2.51 KB
#include "ssr.h"

#include <cstring>

#include "pipelines.h"
#include "renderer.h"
#include "shaders/renderer_types.h"

namespace ssr {

Resources create(FrameGraph &fg) {
    Resources out;
    out.output = fg.add_image({
        .desc = {.format = rhi::ImageFormat::RGBA16_FLOAT},
        .name = "fg/ssr/output",
        .lifetime = Lifetime::Transient,
        .size_class = SizeOp::Swapchain,
        .view = {.type = rhi::ImageViewType::Sampled},
    });
    return out;
}

void record(
    rhi::Device &device,
    Pipelines &pipelines,
    rhi::ShaderCompiler &sc,
    FrameGraph &fg,
    Resources &res,
    ImageHandle color,
    ImageHandle depth,
    ImageHandle normal,
    ImageHandle hiz
) {
    rhi::ComputePipelineDesc pd;
    pd.device = &device;
    pd.set_shader(sc, "src/passes/ssr/ssr.slang", "csMain");
    rhi::ComputePipeline &pipeline = pipelines.add_compute("SSR", pd);

    auto &builder = fg.add_pass("SSR");
    builder.read(color, rhi::ResourceState::TextureSampleNonFragment);
    builder.read(depth, rhi::ResourceState::TextureSampleNonFragment);
    builder.read(normal, rhi::ResourceState::TextureSampleNonFragment);
    if (hiz.is_valid()) {
        builder.read(hiz, rhi::ResourceState::TextureSampleNonFragment);
    }
    builder.write(res.output, rhi::ResourceState::StorageReadWrite);

    // Whole-image storage view resolved once per compile(); execute only reads.
    res.storage_view = fg.request_extra_view(res.output, false);

    builder.execute([=, &pipeline](PassContext &ctx) {
        rhi::set_pipeline(ctx.cmd, pipeline);

        SsrPushConstants pc{};
        pc.color = (u32)ctx.view(color);
        pc.depth = (u32)ctx.view(depth);
        pc.normal = (u32)ctx.view(normal);
        pc.output = (u32)ctx.view_extra(res.storage_view);
        pc.frame = (u64)ctx.render_data->frame_ubo_view[ctx.frame_index].slot;
        pc.width = ctx.render_width;
        pc.height = ctx.render_height;
        pc.max_dist = 50.0f;
        pc.thickness = 0.005f;
        pc.max_steps = 64;
        pc.stride = 50.0f / 64.0f;

        {
            static_assert(sizeof(pc) <= 128, "push constants exceed global 128B range");
            char pc128[128] = {};
            std::memcpy(pc128, &pc, sizeof(pc));
            rhi::set_constants(ctx.cmd, pipeline, rhi::ShaderStage::ALL, sizeof(pc128), pc128);
        }

        u32 gx = (ctx.render_width + 7u) / 8u;
        u32 gy = (ctx.render_height + 7u) / 8u;
        if (gx > 0 && gy > 0) {
            rhi::dispatch(ctx.cmd, gx, gy);
        }
    });
}

} // namespace ssr