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 { ...@@ -93,8 +93,11 @@ namespace mirrage::renderer {
return render_pass_id_of<Animation_pass_factory>(); return render_pass_id_of<Animation_pass_factory>();
} }
auto create_pass(Deferred_renderer&, util::maybe<ecs::Entity_manager&>, Engine&, bool&) auto create_pass(Deferred_renderer&,
-> std::unique_ptr<Render_pass> override; 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; auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t>, int) -> int override;
......
...@@ -35,6 +35,7 @@ namespace mirrage::renderer { ...@@ -35,6 +35,7 @@ namespace mirrage::renderer {
} }
auto create_pass(Deferred_renderer&, auto create_pass(Deferred_renderer&,
std::shared_ptr<void>,
util::maybe<ecs::Entity_manager&>, util::maybe<ecs::Entity_manager&>,
Engine&, Engine&,
bool& write_first_pp_buffer) -> std::unique_ptr<Render_pass> override; bool& write_first_pp_buffer) -> std::unique_ptr<Render_pass> override;
......
...@@ -35,6 +35,7 @@ namespace mirrage::renderer { ...@@ -35,6 +35,7 @@ namespace mirrage::renderer {
auto id() const noexcept -> Render_pass_id override { return render_pass_id_of<Blit_pass_factory>(); } auto id() const noexcept -> Render_pass_id override { return render_pass_id_of<Blit_pass_factory>(); }
auto create_pass(Deferred_renderer&, auto create_pass(Deferred_renderer&,
std::shared_ptr<void>,
util::maybe<ecs::Entity_manager&>, util::maybe<ecs::Entity_manager&>,
Engine&, Engine&,
bool& write_first_pp_buffer) -> std::unique_ptr<Render_pass> override; bool& write_first_pp_buffer) -> std::unique_ptr<Render_pass> override;
......
...@@ -55,8 +55,11 @@ namespace mirrage::renderer { ...@@ -55,8 +55,11 @@ namespace mirrage::renderer {
return render_pass_id_of<Bloom_pass_factory>(); return render_pass_id_of<Bloom_pass_factory>();
} }
auto create_pass(Deferred_renderer&, util::maybe<ecs::Entity_manager&>, Engine&, bool&) auto create_pass(Deferred_renderer&,
-> std::unique_ptr<Render_pass> override; 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) auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t> graphics_queue, int current_score)
-> int override; -> int override;
......
...@@ -32,6 +32,7 @@ namespace mirrage::renderer { ...@@ -32,6 +32,7 @@ namespace mirrage::renderer {
} }
auto create_pass(Deferred_renderer&, auto create_pass(Deferred_renderer&,
std::shared_ptr<void>,
util::maybe<ecs::Entity_manager&>, util::maybe<ecs::Entity_manager&>,
Engine&, Engine&,
bool& write_first_pp_buffer) -> std::unique_ptr<Render_pass> override; bool& write_first_pp_buffer) -> std::unique_ptr<Render_pass> override;
......
...@@ -35,8 +35,11 @@ namespace mirrage::renderer { ...@@ -35,8 +35,11 @@ namespace mirrage::renderer {
return render_pass_id_of<Debug_draw_pass_factory>(); return render_pass_id_of<Debug_draw_pass_factory>();
} }
auto create_pass(Deferred_renderer&, util::maybe<ecs::Entity_manager&>, Engine&, bool&) auto create_pass(Deferred_renderer&,
-> std::unique_ptr<Render_pass> override; 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) auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t> graphics_queue, int current_score)
-> int override; -> int override;
......
...@@ -57,8 +57,11 @@ namespace mirrage::renderer { ...@@ -57,8 +57,11 @@ namespace mirrage::renderer {
return render_pass_id_of<Deferred_pass_factory>(); return render_pass_id_of<Deferred_pass_factory>();
} }
auto create_pass(Deferred_renderer&, util::maybe<ecs::Entity_manager&>, Engine&, bool&) auto create_pass(Deferred_renderer&,
-> std::unique_ptr<Render_pass> override; 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; auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t>, int) -> int override;
......
...@@ -53,8 +53,11 @@ namespace mirrage::renderer { ...@@ -53,8 +53,11 @@ namespace mirrage::renderer {
return render_pass_id_of<Depth_of_field_pass_factory>(); return render_pass_id_of<Depth_of_field_pass_factory>();
} }
auto create_pass(Deferred_renderer&, util::maybe<ecs::Entity_manager&>, Engine&, bool&) auto create_pass(Deferred_renderer&,
-> std::unique_ptr<Render_pass> override; 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; auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t>, int) -> int override;
......
...@@ -30,8 +30,11 @@ namespace mirrage::renderer { ...@@ -30,8 +30,11 @@ namespace mirrage::renderer {
return render_pass_id_of<Frustum_culling_pass_factory>(); return render_pass_id_of<Frustum_culling_pass_factory>();
} }
auto create_pass(Deferred_renderer&, util::maybe<ecs::Entity_manager&>, Engine&, bool&) auto create_pass(Deferred_renderer&,
-> std::unique_ptr<Render_pass> override; 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; auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t>, int) -> int override;
......
...@@ -43,8 +43,11 @@ namespace mirrage::renderer { ...@@ -43,8 +43,11 @@ namespace mirrage::renderer {
return render_pass_id_of<Gen_mipmap_pass_factory>(); return render_pass_id_of<Gen_mipmap_pass_factory>();
} }
auto create_pass(Deferred_renderer&, util::maybe<ecs::Entity_manager&>, Engine&, bool&) auto create_pass(Deferred_renderer&,
-> std::unique_ptr<Render_pass> override; 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; auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t>, int) -> int override;
......
...@@ -136,8 +136,11 @@ namespace mirrage::renderer { ...@@ -136,8 +136,11 @@ namespace mirrage::renderer {
public: public:
auto id() const noexcept -> Render_pass_id override { return render_pass_id_of<Gi_pass_factory>(); } 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&) auto create_pass(Deferred_renderer&,
-> std::unique_ptr<Render_pass> override; 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; auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t>, int) -> int override;
......
...@@ -18,7 +18,7 @@ namespace mirrage::renderer { ...@@ -18,7 +18,7 @@ namespace mirrage::renderer {
public: public:
using Factory = Gui_pass_factory; 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; void update(util::Time dt) override;
...@@ -31,6 +31,8 @@ namespace mirrage::renderer { ...@@ -31,6 +31,8 @@ namespace mirrage::renderer {
auto name() const noexcept -> const char* override { return "GUI"; } auto name() const noexcept -> const char* override { return "GUI"; }
auto extract_persistent_state() -> std::shared_ptr<void> override;
protected: protected:
void prepare_draw(std::size_t index_count, void prepare_draw(std::size_t index_count,
std::size_t vertex_count, std::size_t vertex_count,
...@@ -65,20 +67,34 @@ namespace mirrage::renderer { ...@@ -65,20 +67,34 @@ namespace mirrage::renderer {
bool initialized = false; bool initialized = false;
}; };
struct Texture_cache {
Deferred_renderer& _renderer;
vk::UniqueSampler _sampler;
vk::UniqueDescriptorSetLayout _descriptor_set_layout;
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; Deferred_renderer& _renderer;
std::vector<graphic::Framebuffer> _framebuffers;
vk::UniqueSampler _sampler; vk::UniqueSampler _sampler;
vk::UniqueDescriptorSetLayout _descriptor_set_layout; vk::UniqueDescriptorSetLayout _descriptor_set_layout;
std::shared_ptr<Texture_cache> _texture_cache;
std::vector<graphic::Framebuffer> _framebuffers;
graphic::Render_pass _render_pass; graphic::Render_pass _render_pass;
graphic::DescriptorSet _descriptor_set; graphic::DescriptorSet _descriptor_set;
graphic::Streamed_buffer _mesh_buffer; 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;
// temporary values used during draw // temporary values used during draw
util::maybe<std::uintptr_t> _bound_texture_handle = util::nothing; util::maybe<std::uintptr_t> _bound_texture_handle = util::nothing;
util::maybe<vk::CommandBuffer> _current_command_buffer; util::maybe<vk::CommandBuffer> _current_command_buffer;
...@@ -92,8 +108,11 @@ namespace mirrage::renderer { ...@@ -92,8 +108,11 @@ namespace mirrage::renderer {
auto requires_gbuffer() const noexcept -> bool override { return false; } auto requires_gbuffer() const noexcept -> bool override { return false; }
auto create_pass(Deferred_renderer&, util::maybe<ecs::Entity_manager&>, Engine&, bool&) auto create_pass(Deferred_renderer&,
-> std::unique_ptr<Render_pass> override; 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; auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t>, int) -> int override;
......
...@@ -96,8 +96,11 @@ namespace mirrage::renderer { ...@@ -96,8 +96,11 @@ namespace mirrage::renderer {
return render_pass_id_of<Particle_pass_factory>(); return render_pass_id_of<Particle_pass_factory>();
} }
auto create_pass(Deferred_renderer&, util::maybe<ecs::Entity_manager&>, Engine&, bool&) auto create_pass(Deferred_renderer&,
-> std::unique_ptr<Render_pass> override; 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; auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t>, int) -> int override;
......
...@@ -60,8 +60,11 @@ namespace mirrage::renderer { ...@@ -60,8 +60,11 @@ namespace mirrage::renderer {
return render_pass_id_of<Shadowmapping_pass_factory>(); return render_pass_id_of<Shadowmapping_pass_factory>();
} }
auto create_pass(Deferred_renderer&, util::maybe<ecs::Entity_manager&>, Engine&, bool&) auto create_pass(Deferred_renderer&,
-> std::unique_ptr<Render_pass> override; 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; auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t>, int) -> int override;
......
...@@ -44,8 +44,11 @@ namespace mirrage::renderer { ...@@ -44,8 +44,11 @@ namespace mirrage::renderer {
public: public:
auto id() const noexcept -> Render_pass_id override { return render_pass_id_of<Ssao_pass_factory>(); } 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&) auto create_pass(Deferred_renderer&,
-> std::unique_ptr<Render_pass> override; 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; auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t>, int) -> int override;
......
...@@ -53,8 +53,11 @@ namespace mirrage::renderer { ...@@ -53,8 +53,11 @@ namespace mirrage::renderer {
public: public:
auto id() const noexcept -> Render_pass_id override { return render_pass_id_of<Taa_pass_factory>(); } 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&) auto create_pass(Deferred_renderer&,
-> std::unique_ptr<Render_pass> override; 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; auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t>, int) -> int override;
......
...@@ -72,8 +72,11 @@ namespace mirrage::renderer { ...@@ -72,8 +72,11 @@ namespace mirrage::renderer {
return render_pass_id_of<Tone_mapping_pass_factory>(); return render_pass_id_of<Tone_mapping_pass_factory>();
} }
auto create_pass(Deferred_renderer&, util::maybe<ecs::Entity_manager&>, Engine&, bool&) auto create_pass(Deferred_renderer&,
-> std::unique_ptr<Render_pass> override; 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; auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t>, int) -> int override;
......
...@@ -50,8 +50,11 @@ namespace mirrage::renderer { ...@@ -50,8 +50,11 @@ namespace mirrage::renderer {
return render_pass_id_of<Transparent_pass_factory>(); return render_pass_id_of<Transparent_pass_factory>();
} }
auto create_pass(Deferred_renderer&, util::maybe<ecs::Entity_manager&>, Engine&, bool&) auto create_pass(Deferred_renderer&,
-> std::unique_ptr<Render_pass> override; 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; auto rank_device(vk::PhysicalDevice, util::maybe<std::uint32_t>, int) -> int override;
......
...@@ -172,6 +172,10 @@ namespace mirrage::renderer { ...@@ -172,6 +172,10 @@ namespace mirrage::renderer {
virtual void process_camera(Camera_state&) {} //< allows passes to modify the current camera virtual void process_camera(Camera_state&) {} //< allows passes to modify the current camera
virtual auto name() const noexcept -> const char* = 0; 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; using Render_pass_id = util::type_uid_t;
...@@ -184,6 +188,7 @@ namespace mirrage::renderer { ...@@ -184,6 +188,7 @@ namespace mirrage::renderer {
virtual auto id() const noexcept -> Render_pass_id = 0; virtual auto id() const noexcept -> Render_pass_id = 0;
virtual auto create_pass(Deferred_renderer&, virtual auto create_pass(Deferred_renderer&,
std::shared_ptr<void> last_state,
util::maybe<ecs::Entity_manager&>, util::maybe<ecs::Entity_manager&>,
Engine&, Engine&,
bool& write_first_pp_buffer) -> std::unique_ptr<Render_pass> = 0; bool& write_first_pp_buffer) -> std::unique_ptr<Render_pass> = 0;
......
...@@ -101,7 +101,8 @@ namespace mirrage::renderer { ...@@ -101,7 +101,8 @@ namespace mirrage::renderer {
, _pass_factories(std::move(passes)) , _pass_factories(std::move(passes))
, _passes(util::map(_pass_factories, , _passes(util::map(_pass_factories,
[&, write_first_pp_buffer = true](auto& factory) mutable { [&, 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) , _cameras(ecs.is_some() ? util::justPtr(&ecs.get_or_throw().list<Camera_comp>()) : util::nothing)
{ {
...@@ -130,9 +131,15 @@ namespace mirrage::renderer { ...@@ -130,9 +131,15 @@ namespace mirrage::renderer {
LOG(plog::warning) << "--recreate"; LOG(plog::warning) << "--recreate";
device().wait_idle(); device().wait_idle();
auto persisted_pass_states = std::vector<std::shared_ptr<void>>();
for(auto& pass : _passes) { for(auto& pass : _passes) {
if(pass) if(pass) {
persisted_pass_states.emplace_back(pass->extract_persistent_state());
pass.reset(); pass.reset();
} else {
persisted_pass_states.emplace_back();
}
} }
if(gbuffer_required(_pass_factories)) { if(gbuffer_required(_pass_factories)) {
...@@ -146,10 +153,10 @@ namespace mirrage::renderer { ...@@ -146,10 +153,10 @@ namespace mirrage::renderer {
auto write_first_pp_buffer = true; auto write_first_pp_buffer = true;
for(auto i = std::size_t(0); i < _passes.size(); i++) { for(auto i = std::size_t(0); i < _passes.size(); i++) {
_passes[i] = _pass_factories.at(i)->create_pass( _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(); 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