Commit e4d4dcc3 authored by Florian Oetke's avatar Florian Oetke
Browse files

fixed crash on resize caused by gui_pass using loaded textures on deferred_renderer recreation

parent 34621d64
Pipeline #3119 passed with stage
in 19 minutes and 10 seconds
......@@ -93,8 +93,11 @@ namespace mirrage::renderer {
return render_pass_id_of<Animation_pass_factory>();
}
auto create_pass(Deferred_renderer&, util::maybe<ecs::Entity_manager&>, Engine&, bool&)
-> std::unique_ptr<Render_pass> override;
auto create_pass(Deferred_renderer&,
std::shared_ptr<void>,
util::maybe<ecs::Entity_manager&>,
Engine&,
bool&) -> std::unique_ptr<Render_pass> override;
auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t>, int) -> int override;
......
......@@ -35,6 +35,7 @@ namespace mirrage::renderer {
}
auto create_pass(Deferred_renderer&,
std::shared_ptr<void>,
util::maybe<ecs::Entity_manager&>,
Engine&,
bool& write_first_pp_buffer) -> std::unique_ptr<Render_pass> override;
......
......@@ -35,6 +35,7 @@ namespace mirrage::renderer {
auto id() const noexcept -> Render_pass_id override { return render_pass_id_of<Blit_pass_factory>(); }
auto create_pass(Deferred_renderer&,
std::shared_ptr<void>,
util::maybe<ecs::Entity_manager&>,
Engine&,
bool& write_first_pp_buffer) -> std::unique_ptr<Render_pass> override;
......
......@@ -55,8 +55,11 @@ namespace mirrage::renderer {
return render_pass_id_of<Bloom_pass_factory>();
}
auto create_pass(Deferred_renderer&, util::maybe<ecs::Entity_manager&>, Engine&, bool&)
-> std::unique_ptr<Render_pass> override;
auto create_pass(Deferred_renderer&,
std::shared_ptr<void>,
util::maybe<ecs::Entity_manager&>,
Engine&,
bool&) -> std::unique_ptr<Render_pass> override;
auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t> graphics_queue, int current_score)
-> int override;
......
......@@ -32,6 +32,7 @@ namespace mirrage::renderer {
}
auto create_pass(Deferred_renderer&,
std::shared_ptr<void>,
util::maybe<ecs::Entity_manager&>,
Engine&,
bool& write_first_pp_buffer) -> std::unique_ptr<Render_pass> override;
......
......@@ -35,8 +35,11 @@ namespace mirrage::renderer {
return render_pass_id_of<Debug_draw_pass_factory>();
}
auto create_pass(Deferred_renderer&, util::maybe<ecs::Entity_manager&>, Engine&, bool&)
-> std::unique_ptr<Render_pass> override;
auto create_pass(Deferred_renderer&,
std::shared_ptr<void>,
util::maybe<ecs::Entity_manager&>,
Engine&,
bool&) -> std::unique_ptr<Render_pass> override;
auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t> graphics_queue, int current_score)
-> int override;
......
......@@ -57,8 +57,11 @@ namespace mirrage::renderer {
return render_pass_id_of<Deferred_pass_factory>();
}
auto create_pass(Deferred_renderer&, util::maybe<ecs::Entity_manager&>, Engine&, bool&)
-> std::unique_ptr<Render_pass> override;
auto create_pass(Deferred_renderer&,
std::shared_ptr<void>,
util::maybe<ecs::Entity_manager&>,
Engine&,
bool&) -> std::unique_ptr<Render_pass> override;
auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t>, int) -> int override;
......
......@@ -53,8 +53,11 @@ namespace mirrage::renderer {
return render_pass_id_of<Depth_of_field_pass_factory>();
}
auto create_pass(Deferred_renderer&, util::maybe<ecs::Entity_manager&>, Engine&, bool&)
-> std::unique_ptr<Render_pass> override;
auto create_pass(Deferred_renderer&,
std::shared_ptr<void>,
util::maybe<ecs::Entity_manager&>,
Engine&,
bool&) -> std::unique_ptr<Render_pass> override;
auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t>, int) -> int override;
......
......@@ -30,8 +30,11 @@ namespace mirrage::renderer {
return render_pass_id_of<Frustum_culling_pass_factory>();
}
auto create_pass(Deferred_renderer&, util::maybe<ecs::Entity_manager&>, Engine&, bool&)
-> std::unique_ptr<Render_pass> override;
auto create_pass(Deferred_renderer&,
std::shared_ptr<void>,
util::maybe<ecs::Entity_manager&>,
Engine&,
bool&) -> std::unique_ptr<Render_pass> override;
auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t>, int) -> int override;
......
......@@ -43,8 +43,11 @@ namespace mirrage::renderer {
return render_pass_id_of<Gen_mipmap_pass_factory>();
}
auto create_pass(Deferred_renderer&, util::maybe<ecs::Entity_manager&>, Engine&, bool&)
-> std::unique_ptr<Render_pass> override;
auto create_pass(Deferred_renderer&,
std::shared_ptr<void>,
util::maybe<ecs::Entity_manager&>,
Engine&,
bool&) -> std::unique_ptr<Render_pass> override;
auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t>, int) -> int override;
......
......@@ -136,8 +136,11 @@ namespace mirrage::renderer {
public:
auto id() const noexcept -> Render_pass_id override { return render_pass_id_of<Gi_pass_factory>(); }
auto create_pass(Deferred_renderer&, util::maybe<ecs::Entity_manager&>, Engine&, bool&)
-> std::unique_ptr<Render_pass> override;
auto create_pass(Deferred_renderer&,
std::shared_ptr<void>,
util::maybe<ecs::Entity_manager&>,
Engine&,
bool&) -> std::unique_ptr<Render_pass> override;
auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t>, int) -> int override;
......
......@@ -18,7 +18,7 @@ namespace mirrage::renderer {
public:
using Factory = Gui_pass_factory;
Gui_pass(Deferred_renderer&, Engine&);
Gui_pass(Deferred_renderer&, Engine&, std::shared_ptr<void> last_state);
void update(util::Time dt) override;
......@@ -31,6 +31,8 @@ namespace mirrage::renderer {
auto name() const noexcept -> const char* override { return "GUI"; }
auto extract_persistent_state() -> std::shared_ptr<void> override;
protected:
void prepare_draw(std::size_t index_count,
std::size_t vertex_count,
......@@ -65,20 +67,34 @@ namespace mirrage::renderer {
bool initialized = false;
};
struct Texture_cache {
Deferred_renderer& _renderer;
std::vector<graphic::Framebuffer> _framebuffers;
vk::UniqueSampler _sampler;
vk::UniqueDescriptorSetLayout _descriptor_set_layout;
graphic::Render_pass _render_pass;
graphic::DescriptorSet _descriptor_set;
graphic::Streamed_buffer _mesh_buffer;
// texture cache/store
std::uintptr_t _next_texture_handle = 0;
std::vector<std::shared_ptr<Loaded_texture>> _loaded_textures;
std::unordered_map<asset::AID, std::weak_ptr<void>> _loaded_textures_by_aid;
std::unordered_map<std::uintptr_t, std::weak_ptr<Loaded_texture>> _loaded_textures_by_handle;
Texture_cache(Deferred_renderer&);
void shrink();
auto load_texture(int width, int height, int channels, const std::uint8_t* data)
-> std::shared_ptr<void>;
auto load_texture(const asset::AID&) -> std::shared_ptr<void>;
};
Deferred_renderer& _renderer;
vk::UniqueSampler _sampler;
vk::UniqueDescriptorSetLayout _descriptor_set_layout;
std::shared_ptr<Texture_cache> _texture_cache;
std::vector<graphic::Framebuffer> _framebuffers;
graphic::Render_pass _render_pass;
graphic::DescriptorSet _descriptor_set;
graphic::Streamed_buffer _mesh_buffer;
// temporary values used during draw
util::maybe<std::uintptr_t> _bound_texture_handle = util::nothing;
util::maybe<vk::CommandBuffer> _current_command_buffer;
......@@ -92,8 +108,11 @@ namespace mirrage::renderer {
auto requires_gbuffer() const noexcept -> bool override { return false; }
auto create_pass(Deferred_renderer&, util::maybe<ecs::Entity_manager&>, Engine&, bool&)
-> std::unique_ptr<Render_pass> override;
auto create_pass(Deferred_renderer&,
std::shared_ptr<void> last_state,
util::maybe<ecs::Entity_manager&>,
Engine&,
bool&) -> std::unique_ptr<Render_pass> override;
auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t>, int) -> int override;
......
......@@ -96,8 +96,11 @@ namespace mirrage::renderer {
return render_pass_id_of<Particle_pass_factory>();
}
auto create_pass(Deferred_renderer&, util::maybe<ecs::Entity_manager&>, Engine&, bool&)
-> std::unique_ptr<Render_pass> override;
auto create_pass(Deferred_renderer&,
std::shared_ptr<void>,
util::maybe<ecs::Entity_manager&>,
Engine&,
bool&) -> std::unique_ptr<Render_pass> override;
auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t>, int) -> int override;
......
......@@ -60,8 +60,11 @@ namespace mirrage::renderer {
return render_pass_id_of<Shadowmapping_pass_factory>();
}
auto create_pass(Deferred_renderer&, util::maybe<ecs::Entity_manager&>, Engine&, bool&)
-> std::unique_ptr<Render_pass> override;
auto create_pass(Deferred_renderer&,
std::shared_ptr<void>,
util::maybe<ecs::Entity_manager&>,
Engine&,
bool&) -> std::unique_ptr<Render_pass> override;
auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t>, int) -> int override;
......
......@@ -44,8 +44,11 @@ namespace mirrage::renderer {
public:
auto id() const noexcept -> Render_pass_id override { return render_pass_id_of<Ssao_pass_factory>(); }
auto create_pass(Deferred_renderer&, util::maybe<ecs::Entity_manager&>, Engine&, bool&)
-> std::unique_ptr<Render_pass> override;
auto create_pass(Deferred_renderer&,
std::shared_ptr<void>,
util::maybe<ecs::Entity_manager&>,
Engine&,
bool&) -> std::unique_ptr<Render_pass> override;
auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t>, int) -> int override;
......
......@@ -53,8 +53,11 @@ namespace mirrage::renderer {
public:
auto id() const noexcept -> Render_pass_id override { return render_pass_id_of<Taa_pass_factory>(); }
auto create_pass(Deferred_renderer&, util::maybe<ecs::Entity_manager&>, Engine&, bool&)
-> std::unique_ptr<Render_pass> override;
auto create_pass(Deferred_renderer&,
std::shared_ptr<void>,
util::maybe<ecs::Entity_manager&>,
Engine&,
bool&) -> std::unique_ptr<Render_pass> override;
auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t>, int) -> int override;
......
......@@ -72,8 +72,11 @@ namespace mirrage::renderer {
return render_pass_id_of<Tone_mapping_pass_factory>();
}
auto create_pass(Deferred_renderer&, util::maybe<ecs::Entity_manager&>, Engine&, bool&)
-> std::unique_ptr<Render_pass> override;
auto create_pass(Deferred_renderer&,
std::shared_ptr<void>,
util::maybe<ecs::Entity_manager&>,
Engine&,
bool&) -> std::unique_ptr<Render_pass> override;
auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t>, int) -> int override;
......
......@@ -50,8 +50,11 @@ namespace mirrage::renderer {
return render_pass_id_of<Transparent_pass_factory>();
}
auto create_pass(Deferred_renderer&, util::maybe<ecs::Entity_manager&>, Engine&, bool&)
-> std::unique_ptr<Render_pass> override;
auto create_pass(Deferred_renderer&,
std::shared_ptr<void>,
util::maybe<ecs::Entity_manager&>,
Engine&,
bool&) -> std::unique_ptr<Render_pass> override;
auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t>, int) -> int override;
......
......@@ -172,6 +172,10 @@ namespace mirrage::renderer {
virtual void process_camera(Camera_state&) {} //< allows passes to modify the current camera
virtual auto name() const noexcept -> const char* = 0;
/// API to allow render passes to save some of their state (e.g. loaded textures/data)
/// across pipeline/renderer recreation
virtual auto extract_persistent_state() -> std::shared_ptr<void> { return {}; }
};
using Render_pass_id = util::type_uid_t;
......@@ -184,6 +188,7 @@ namespace mirrage::renderer {
virtual auto id() const noexcept -> Render_pass_id = 0;
virtual auto create_pass(Deferred_renderer&,
std::shared_ptr<void> last_state,
util::maybe<ecs::Entity_manager&>,
Engine&,
bool& write_first_pp_buffer) -> std::unique_ptr<Render_pass> = 0;
......
......@@ -101,7 +101,8 @@ namespace mirrage::renderer {
, _pass_factories(std::move(passes))
, _passes(util::map(_pass_factories,
[&, write_first_pp_buffer = true](auto& factory) mutable {
return factory->create_pass(*this, ecs, engine, write_first_pp_buffer);
return factory->create_pass(
*this, std::shared_ptr<void>{}, ecs, engine, write_first_pp_buffer);
}))
, _cameras(ecs.is_some() ? util::justPtr(&ecs.get_or_throw().list<Camera_comp>()) : util::nothing)
{
......@@ -130,9 +131,15 @@ namespace mirrage::renderer {
LOG(plog::warning) << "--recreate";
device().wait_idle();
auto persisted_pass_states = std::vector<std::shared_ptr<void>>();
for(auto& pass : _passes) {
if(pass)
if(pass) {
persisted_pass_states.emplace_back(pass->extract_persistent_state());
pass.reset();
} else {
persisted_pass_states.emplace_back();
}
}
if(gbuffer_required(_pass_factories)) {
......@@ -146,10 +153,10 @@ namespace mirrage::renderer {
auto write_first_pp_buffer = true;
for(auto i = std::size_t(0); i < _passes.size(); i++) {
_passes[i] = _pass_factories.at(i)->create_pass(
*this, _entity_manager, *_engine, write_first_pp_buffer);
*this, persisted_pass_states.at(i), _entity_manager, *_engine, write_first_pp_buffer);
}
_profiler = graphic::Profiler(device(), 64);
_profiler = graphic::Profiler(device(), 128);
device().wait_idle();
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment