#include "pipelines.h"
#include <volk.h>
#include "core/logger.h"
Pipelines::Pipelines(rhi::Device &device, rhi::ShaderCompiler &compiler) : device(device), compiler(compiler) {
}
rhi::RenderPipeline &Pipelines::add_render(const char *name, rhi::RenderPipelineDesc desc) {
desc.name = name;
u64 mtime = rhi::get_file_last_write_time(desc.shader_path.c_str());
assert(desc.device != nullptr && "Pipelines::add_render: RenderPipelineDesc::device not assigned");
rhi::RenderPipeline p = desc.build();
auto it = render_entries.emplace(name, RenderEntry{std::move(desc), p, mtime}).first;
return it->second.pipeline;
}
rhi::ComputePipeline &Pipelines::add_compute(const char *name, rhi::ComputePipelineDesc desc) {
desc.name = name;
u64 mtime = rhi::get_file_last_write_time(desc.shader_path.c_str());
assert(desc.device != nullptr && "Pipelines::add_compute: ComputePipelineDesc::device not assigned");
rhi::ComputePipeline p = desc.build();
auto it = compute_entries.emplace(name, ComputeEntry{std::move(desc), p, mtime}).first;
return it->second.pipeline;
}
rhi::RenderPipeline &Pipelines::get_render(const char *name) {
return render_entries.at(name).pipeline;
}
rhi::ComputePipeline &Pipelines::get_compute(const char *name) {
return compute_entries.at(name).pipeline;
}
void Pipelines::clear() {
for (auto &[name, e] : render_entries) {
if (rhi::valid(e.pipeline)) {
rhi::destroy_pipeline(device, e.pipeline);
}
}
render_entries.clear();
for (auto &[name, e] : compute_entries) {
if (rhi::valid(e.pipeline)) {
rhi::destroy_pipeline(device, e.pipeline);
}
}
compute_entries.clear();
}
void Pipelines::reload() {
if (!compiler.recreate_session()) {
VEL_ERROR("Reload aborted — failed to create fresh Slang session");
return;
}
bool any = false;
for (auto &[name, e] : render_entries) {
u64 mtime = rhi::get_file_last_write_time(e.desc.shader_path.c_str());
if (mtime == 0 || mtime == e.source_mtime) {
continue;
}
rhi::RenderPipelineDesc new_desc = e.desc;
new_desc.set_shaders(
compiler, new_desc.shader_path.c_str(), new_desc.vs_entry.c_str(), new_desc.fs_entry.c_str()
);
rhi::RenderPipeline np = new_desc.build();
if (!rhi::valid(np)) {
VEL_ERROR("Reload failed for '{}' — keeping old version", name);
continue;
}
rhi::device_wait_idle(device);
rhi::destroy_pipeline(device, e.pipeline);
e.pipeline = np;
e.source_mtime = mtime;
VEL_INFO("Reloaded '{}'", name);
any = true;
}
for (auto &[name, e] : compute_entries) {
u64 mtime = rhi::get_file_last_write_time(e.desc.shader_path.c_str());
if (mtime == 0 || mtime == e.source_mtime) {
continue;
}
rhi::ComputePipelineDesc new_desc = e.desc;
new_desc.set_shader(compiler, new_desc.shader_path.c_str(), new_desc.cs_entry.c_str());
rhi::ComputePipeline np = new_desc.build();
if (!rhi::valid(np)) {
VEL_ERROR("Reload failed for '{}' — keeping old version", name);
continue;
}
rhi::device_wait_idle(device);
rhi::destroy_pipeline(device, e.pipeline);
e.pipeline = np;
e.source_mtime = mtime;
VEL_INFO("Reloaded '{}'", name);
any = true;
}
if (!any) {
VEL_INFO("No shaders changed");
}
}