Skip to content

Commit d3385d0

Browse files
committed
Add back shader reloading for the render graph
1 parent 3342ad8 commit d3385d0

File tree

6 files changed

+50
-24
lines changed

6 files changed

+50
-24
lines changed

Lumen.vcxproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@
163163
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions);_SILENCE_CXX20_CISO646_REMOVED_WARNING;TINYEXR_USE_MINIZ;TINYEXR_USE_MINIZ</PreprocessorDefinitions>
164164
<ConformanceMode>true</ConformanceMode>
165165
<AdditionalIncludeDirectories>$(SolutionDir)libs\glm;$(SolutionDir)libs\glfw\include;$(VULKAN_SDK)\Include;$(SolutionDir)libs\spdlog\include;$(SolutionDir)src;$(SolutionDir)libs\stb_image;$(SolutionDir)libs\gli;$(SolutionDir)libs\tinygltf;$(SolutionDir)libs\imgui;$(SolutionDir)libs\nvvk;$(SolutionDir)libs;C:\VulkanSDK\1.3.216.0\Include</AdditionalIncludeDirectories>
166-
<LanguageStandard>stdcpplatest</LanguageStandard>
166+
<LanguageStandard>stdcpp20</LanguageStandard>
167167
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
168168
<PrecompiledHeader>Use</PrecompiledHeader>
169169
<PrecompiledHeaderFile>LumenPCH.h</PrecompiledHeaderFile>

src/Framework/Pipeline.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
#include "Pipeline.h"
33
#include "VkUtils.h"
44

5-
Pipeline::Pipeline(VulkanContext* ctx, size_t pass_idx, const std::string& name)
6-
: ctx(ctx), pass_idx(pass_idx), name(name) {}
5+
Pipeline::Pipeline(VulkanContext* ctx, const std::string& name)
6+
: ctx(ctx),name(name) {}
77

88
void Pipeline::reload() {}
99

src/Framework/Pipeline.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ struct PipelineTrace {
1616
struct Pipeline {
1717
public:
1818
enum class PipelineType { GFX = 0, RT = 1, COMPUTE = 2 };
19-
Pipeline(VulkanContext* ctx, size_t pass_idx, const std::string& name);
19+
Pipeline(VulkanContext* ctx, const std::string& name);
2020
void reload();
2121
void cleanup();
2222
void create_gfx_pipeline(const GraphicsPassSettings& settings, const std::vector<uint32_t>& descriptor_counts,
@@ -55,7 +55,6 @@ struct Pipeline {
5555
VkWriteDescriptorSetAccelerationStructureKHR tlas_info = {};
5656
SBTWrapper sbt_wrapper;
5757
PipelineType type;
58-
size_t pass_idx;
5958
bool running = true;
6059
VkDescriptorUpdateTemplate update_template = nullptr;
6160
VkShaderStageFlags pc_stages = 0;

src/Framework/RenderGraph.cpp

+33-10
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// Possible solution: Make compilation with debugPrintf shaders synchronous?
99

1010
#define DIRTY_CHECK(x) \
11-
if (!x) { \
11+
if (!(x)) { \
1212
return *this; \
1313
}
1414
static VkPipelineStageFlags get_pipeline_stage(PassType pass_type, VkAccessFlags access_flags) {
@@ -292,14 +292,22 @@ RenderPass& RenderGraph::add_rt(const std::string& name, const RTPassSettings& s
292292
auto& storage = pipeline_cache[name];
293293
if (!recording && storage.pass_idxs.size()) {
294294
auto idx = storage.pass_idxs[storage.offset_idx];
295-
++storage.offset_idx;
296295
passes[idx].active = true;
296+
if (reload_shaders) {
297+
if (storage.offset_idx == 0) {
298+
pipeline_cache[name].pipeline->cleanup();
299+
pipeline_cache[name].pipeline = std::make_unique<Pipeline>(ctx, name);
300+
}
301+
passes[idx].pipeline = pipeline_cache[name].pipeline.get();
302+
}
303+
++storage.offset_idx;
297304
return passes[idx];
298305
}
306+
299307
pipeline = pipeline_cache[name].pipeline.get();
300308
cached = true;
301309
} else {
302-
pipeline_cache[name] = {std::make_unique<Pipeline>(ctx, pass_idx, name)};
310+
pipeline_cache[name] = {std::make_unique<Pipeline>(ctx, name)};
303311
pipeline = pipeline_cache[name].pipeline.get();
304312
}
305313
passes.emplace_back(PassType::RT, pipeline, name, this, pass_idx, settings, cached);
@@ -315,17 +323,24 @@ RenderPass& RenderGraph::add_gfx(const std::string& name, const GraphicsPassSett
315323
auto& storage = pipeline_cache[name];
316324
if (!recording && storage.pass_idxs.size()) {
317325
auto idx = storage.pass_idxs[storage.offset_idx];
318-
++storage.offset_idx;
319326
auto& curr_pass = passes[idx];
320327
curr_pass.gfx_settings->color_outputs = settings.color_outputs;
321328
curr_pass.gfx_settings->depth_output = settings.depth_output;
322329
curr_pass.active = true;
330+
if (reload_shaders) {
331+
if (storage.offset_idx == 0) {
332+
pipeline_cache[name].pipeline->cleanup();
333+
pipeline_cache[name].pipeline = std::make_unique<Pipeline>(ctx, name);
334+
}
335+
passes[idx].pipeline = pipeline_cache[name].pipeline.get();
336+
}
337+
++storage.offset_idx;
323338
return curr_pass;
324339
}
325340
pipeline = pipeline_cache[name].pipeline.get();
326341
cached = true;
327342
} else {
328-
pipeline_cache[name] = {std::make_unique<Pipeline>(ctx, pass_idx, name)};
343+
pipeline_cache[name] = {std::make_unique<Pipeline>(ctx, name)};
329344
pipeline = pipeline_cache[name].pipeline.get();
330345
}
331346
passes.emplace_back(PassType::Graphics, pipeline, name, this, pass_idx, settings, cached);
@@ -342,13 +357,20 @@ RenderPass& RenderGraph::add_compute(const std::string& name, const ComputePassS
342357
if (!recording && storage.pass_idxs.size()) {
343358
auto idx = storage.pass_idxs[storage.offset_idx];
344359
passes[idx].active = true;
360+
if (reload_shaders) {
361+
if (storage.offset_idx == 0) {
362+
pipeline_cache[name].pipeline->cleanup();
363+
pipeline_cache[name].pipeline = std::make_unique<Pipeline>(ctx, name);
364+
}
365+
passes[idx].pipeline = pipeline_cache[name].pipeline.get();
366+
}
345367
++storage.offset_idx;
346368
return passes[idx];
347369
}
348370
pipeline = pipeline_cache[name].pipeline.get();
349371
cached = true;
350372
} else {
351-
pipeline_cache[name] = {std::make_unique<Pipeline>(ctx, pass_idx, name)};
373+
pipeline_cache[name] = {std::make_unique<Pipeline>(ctx, name)};
352374
pipeline = pipeline_cache[name].pipeline.get();
353375
}
354376
passes.emplace_back(PassType::Compute, pipeline, name, this, pass_idx, settings, cached);
@@ -405,7 +427,7 @@ RenderPass& RenderPass::bind_buffer_array(std::vector<Buffer>& buffers) {
405427
}
406428

407429
RenderPass& RenderPass::bind_tlas(const AccelKHR& tlas) {
408-
DIRTY_CHECK(rg->recording);
430+
DIRTY_CHECK(rg->recording || rg->reload_shaders);
409431
pipeline->tlas_info = {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR};
410432
pipeline->tlas_info.accelerationStructureCount = 1;
411433
pipeline->tlas_info.pAccelerationStructures = &tlas.accel;
@@ -526,7 +548,7 @@ RenderPass& RenderPass::copy(const Resource& src, const Resource& dst) {
526548
}
527549

528550
void RenderPass::finalize() {
529-
if (!rg->recording) {
551+
if (!rg->recording && !rg->reload_shaders) {
530552
// Handle resource transitions
531553
transition_resources();
532554
return;
@@ -882,15 +904,15 @@ void RenderGraph::run(VkCommandBuffer cmd) {
882904
img_sync_resources.resize(passes.size());
883905

884906
// Compile shaders and process resources
885-
if (recording) {
907+
if (recording || reload_shaders) {
886908
auto cmp = [](const std::pair<Shader*, RenderPass*>& a, const std::pair<Shader*, RenderPass*>& b) {
887909
return a.first->filename < b.first->filename;
888910
};
889911
std::set<std::pair<Shader*, RenderPass*>, decltype(cmp)> unique_shaders_set;
890912
std::unordered_map<RenderPass*, std::vector<Shader*>> unique_shaders;
891913
std::unordered_map<RenderPass*, std::vector<Shader*>> existing_shaders;
892914

893-
// Recording -> The pass is active by default
915+
// Recording or reload -> The pass is active by default
894916
for (auto i = beginning_pass_idx; i < ending_pass_idx; i++) {
895917
if (passes[i].gfx_settings) {
896918
for (auto& shader : passes[i].gfx_settings->shaders) {
@@ -1013,6 +1035,7 @@ void RenderGraph::reset(VkCommandBuffer cmd) {
10131035
buffer_sync_resources.clear();
10141036
img_sync_resources.clear();
10151037
beginning_pass_idx = ending_pass_idx = 0;
1038+
reload_shaders = false;
10161039
}
10171040

10181041
void RenderGraph::submit(CommandBuffer& cmd) {

src/Framework/RenderGraph.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class RenderGraph {
4040
void destroy();
4141
friend RenderPass;
4242
bool recording = true;
43+
bool reload_shaders = false;
4344
EventPool event_pool;
4445
std::unordered_map<std::string, Buffer*> registered_buffer_pointers;
4546
std::unordered_map<std::string, Shader> shader_cache;
@@ -58,8 +59,7 @@ class RenderGraph {
5859

5960
struct PipelineStorage {
6061
std::unique_ptr<Pipeline> pipeline;
61-
uint32_t offset_idx; // Offset index relative to the pass_idx the
62-
// pipeline holds
62+
uint32_t offset_idx;
6363
std::vector<uint32_t> pass_idxs;
6464
};
6565
VulkanContext* ctx = nullptr;

src/RayTracer/RayTracer.cpp

+11-7
Original file line numberDiff line numberDiff line change
@@ -184,13 +184,7 @@ float RayTracer::draw_frame() {
184184

185185
bool gui_updated = integrator->gui();
186186
updated |= ImGui::Checkbox("Enable ACES tonemapping", &settings.enable_tonemapping);
187-
if (updated || gui_updated) {
188-
ImGui::Render();
189-
auto t_end = glfwGetTime() * 1000;
190-
auto t_diff = t_end - t_begin;
191-
integrator->updated = true;
192-
return (float)t_diff;
193-
}
187+
194188
ImGui::Checkbox("Show camera statistics", &show_cam_stats);
195189
if (show_cam_stats) {
196190
ImGui::PushItemWidth(170);
@@ -201,9 +195,19 @@ float RayTracer::draw_frame() {
201195
}
202196
if (ImGui::Button("Reload shaders")) {
203197
// TODO
198+
vkb.rg->reload_shaders = true;
199+
vkb.rg->shader_cache.clear();
204200
updated |= true;
205201
}
206202

203+
if (updated || gui_updated) {
204+
ImGui::Render();
205+
auto t_end = glfwGetTime() * 1000;
206+
auto t_diff = t_end - t_begin;
207+
integrator->updated = true;
208+
return (float)t_diff;
209+
}
210+
207211

208212
uint32_t image_idx = vkb.prepare_frame();
209213

0 commit comments

Comments
 (0)