Commit 69aa83ca authored by Florian Oetke's avatar Florian Oetke
Browse files

finally fixed these god damn error on renderer recreation

parent 126a53dc
......@@ -62,7 +62,7 @@ namespace mirrage {
, _gui(engine.window().viewport(),
engine.assets(),
engine.input(),
util::tracking_ptr<gui::Gui_renderer>(_meta_system.renderer().find_pass<renderer::Gui_pass>()))
_meta_system.renderer().find_pass<gui::Gui_renderer>())
, _performance_log(util::nothing) {
_camera = _meta_system.entities().emplace("camera");
......
......@@ -111,12 +111,9 @@ namespace mirrage::graphic {
public:
explicit Profiler(Device&, std::size_t max_elements = 32);
Profiler(Profiler&&) = default;
Profiler& operator =(Profiler&&) noexcept;
~Profiler();
void enable() noexcept { _active = true; }
void disable() noexcept { _active = false; }
void enable() noexcept { _active_requested = true; }
void disable() noexcept { _active_requested = false; }
void reset() noexcept;
void start(vk::CommandBuffer);
......@@ -136,7 +133,22 @@ namespace mirrage::graphic {
private:
friend class Push_raii;
using Query_pools = util::ring_buffer<vk::UniqueQueryPool>;
struct Query_pool_entry {
vk::UniqueQueryPool pool;
std::uint32_t requested_queries = 0;
Query_pool_entry() = default;
Query_pool_entry(Device& device, std::uint32_t max_count);
Query_pool_entry(Query_pool_entry&& rhs) noexcept
: pool(std::move(rhs.pool)), requested_queries(rhs.requested_queries) {}
Query_pool_entry& operator=(Query_pool_entry&& rhs) noexcept {
pool = std::move(rhs.pool);
requested_queries = std::move(rhs.requested_queries);
return *this;
}
};
using Query_pools = util::ring_buffer<Query_pool_entry>;
using Result_stack = std::vector<Profiler_result*>;
vk::Device _device;
......@@ -145,8 +157,9 @@ namespace mirrage::graphic {
std::uint32_t _next_query_id = 0;
Profiler_result _last_results;
Query_pools _query_pools;
bool _active = false;
bool _full = false;
bool _active = false;
bool _active_requested = false;
bool _full = false;
Result_stack _current_stack;
util::maybe<vk::CommandBuffer> _current_command_buffer;
......@@ -159,7 +172,5 @@ namespace mirrage::graphic {
auto _generate_query_id() -> std::uint32_t;
void _update_result(Profiler_result&, const std::vector<std::uint32_t>& data);
void _wait_done();
};
}
......@@ -69,62 +69,34 @@ namespace mirrage::graphic {
Profiler::Push_raii::Push_raii(Profiler& profiler) : _profiler(&profiler) {}
Profiler::Query_pool_entry::Query_pool_entry(Device& device, std::uint32_t max_count)
: pool(device.vk_device()->createQueryPoolUnique(
vk::QueryPoolCreateInfo{vk::QueryPoolCreateFlags{}, vk::QueryType::eTimestamp, max_count})) {}
Profiler::Profiler(Device& device, std::size_t max_elements)
: _device(*device.vk_device())
, _ns_per_tick(device.physical_device_properties().limits.timestampPeriod)
, _query_ids(max_elements)
, _last_results("All", _generate_query_id(), _generate_query_id())
, _query_pools(device.max_frames_in_flight(),
[&] {
return _device.createQueryPoolUnique(vk::QueryPoolCreateInfo{
vk::QueryPoolCreateFlags{}, vk::QueryType::eTimestamp, _query_ids});
})
[&] { return Query_pool_entry(device, gsl::narrow<std::uint32_t>(_query_ids)); })
, _query_used(max_elements, false) {}
Profiler& Profiler::operator=(Profiler&& rhs) noexcept {
_wait_done();
_device = std::move(rhs._device);
_ns_per_tick = std::move(rhs._ns_per_tick);
_query_ids = std::move(rhs._query_ids);
_next_query_id = std::move(rhs._next_query_id);
_last_results = std::move(rhs._last_results);
_query_pools = std::move(rhs._query_pools);
_current_stack = std::move(rhs._current_stack);
_current_command_buffer = std::move(rhs._current_command_buffer);
_query_result_buffer = std::move(rhs._query_result_buffer);
_query_used = std::move(rhs._query_used);
return *this;
}
Profiler::~Profiler() { _wait_done(); }
void Profiler::_wait_done() {
_query_pools.pop_while([&](auto& pool) {
auto status = _device.getQueryPoolResults<std::uint32_t>(*pool,
0,
_next_query_id,
_query_result_buffer,
sizeof(std::uint32_t),
vk::QueryResultFlagBits::eWait);
INVARIANT(status == vk::Result::eSuccess, "getQueryPoolResults failed!");
return true;
});
}
void Profiler::reset() noexcept { _last_results.reset(); }
void Profiler::start(vk::CommandBuffer cb) {
_active = _active_requested;
if(!_active || _full)
return;
INVARIANT(_current_stack.empty(), "Profiler::start can not be nested!");
cb.resetQueryPool(*_query_pools.head(), 0, _query_ids);
cb.resetQueryPool(*_query_pools.head().pool, 0, _query_ids);
std::fill(_query_used.begin(), _query_used.end(), false);
cb.writeTimestamp(vk::PipelineStageFlagBits::eAllCommands,
*_query_pools.head(),
*_query_pools.head().pool,
_last_results.query_id_begin());
_query_used[_last_results.query_id_begin()] = true;
......@@ -139,7 +111,7 @@ namespace mirrage::graphic {
"No active command buffer! Has Profiler::start been called?");
cb.writeTimestamp(vk::PipelineStageFlagBits::eAllCommands,
*_query_pools.head(),
*_query_pools.head().pool,
_last_results.query_id_end());
_query_used[_last_results.query_id_end()] = true;
......@@ -150,18 +122,20 @@ namespace mirrage::graphic {
// request timestamps for all unused queryIds
for(auto i = 0u; i < _next_query_id; i++) {
if(!_query_used[i]) {
cb.writeTimestamp(vk::PipelineStageFlagBits::eBottomOfPipe, *_query_pools.head(), i);
cb.writeTimestamp(vk::PipelineStageFlagBits::eBottomOfPipe, *_query_pools.head().pool, i);
}
}
_query_pools.head().requested_queries = _next_query_id;
}
_query_result_buffer.resize(_next_query_id);
_query_pools.pop_while([&](auto& pool) {
_query_pools.pop_while([&](auto& entry) {
// receivce results
auto status = _device.getQueryPoolResults<std::uint32_t>(*pool,
auto status = _device.getQueryPoolResults<std::uint32_t>(*entry.pool,
0,
_next_query_id,
entry.requested_queries,
_query_result_buffer,
sizeof(std::uint32_t),
vk::QueryResultFlags{});
......@@ -177,6 +151,9 @@ namespace mirrage::graphic {
if(_active || _full) {
_full = !_query_pools.advance_head();
if(_full) {
INFO("full");
}
}
_current_command_buffer = util::nothing;
......@@ -204,7 +181,7 @@ namespace mirrage::graphic {
auto& result = _current_stack.back()->get_or_add(name, [&] { return _generate_query_id(); });
_current_stack.emplace_back(&result);
cb.writeTimestamp(stage, *_query_pools.head(), result.query_id_begin());
cb.writeTimestamp(stage, *_query_pools.head().pool, result.query_id_begin());
_query_used[result.query_id_begin()] = true;
......@@ -217,7 +194,7 @@ namespace mirrage::graphic {
"No active command buffer! Has Profiler::start been called?");
cb.writeTimestamp(vk::PipelineStageFlagBits::eAllCommands,
*_query_pools.head(),
*_query_pools.head().pool,
_current_stack.back()->query_id_end());
_query_used[_current_stack.back()->query_id_end()] = true;
......
......@@ -79,7 +79,7 @@ namespace mirrage::gui {
virtual void finalize_draw() = 0;
private:
Gui* _gui;
Gui* _gui = nullptr;
};
// TODO: gamepad input: https://gist.github.com/vurtun/519801825b4ccfad6767
......
......@@ -436,7 +436,7 @@ namespace mirrage::gui {
_last_renderer->_gui = this;
} else {
ERROR("Gui initialized without a valid renderer. Nothing will be drawn!");
WARN("Gui initialized without a valid renderer. Nothing will be drawn!");
}
}
......@@ -447,14 +447,25 @@ namespace mirrage::gui {
}
void Gui::draw() {
if(_renderer.modified(_last_renderer)) {
_init();
}
if(!_impl) {
INFO("no impl");
return;
}
_impl->renderer.draw(_impl->ctx.ctx, _impl->viewport, _impl->screen_size, _impl->ui_matrix);
}
auto Gui::ctx() -> nk_context* {
if(_renderer && _renderer.get() != _last_renderer) {
if(_renderer.modified(_last_renderer)) {
_init();
}
INVARIANT(_impl, "Not initialized when nk_context was requested!");
return &_impl->ctx.ctx;
}
......
......@@ -210,6 +210,8 @@ namespace mirrage::renderer {
auto profiler() noexcept -> auto& { return _profiler; }
private:
friend class Deferred_renderer_factory;
Deferred_renderer_factory* _factory;
ecs::Entity_manager* _entity_manager;
util::maybe<Meta_system&> _meta_system;
......
......@@ -67,11 +67,13 @@ namespace mirrage::renderer {
}
void Deferred_renderer::recreate() {
WARN("--recreate");
device().wait_idle();
for(auto& pass : _passes) {
pass.reset();
}
_gbuffer.reset();
// recreate gbuffer and renderpasses
......@@ -83,6 +85,8 @@ namespace mirrage::renderer {
*this, *_entity_manager, _meta_system, write_first_pp_buffer);
}
_profiler = graphic::Profiler(device(), 64);
device().wait_idle();
}
......@@ -256,6 +260,7 @@ namespace mirrage::renderer {
inst->recreate();
}
}
_device->wait_idle();
}
void Deferred_renderer_factory::_present() {
if(_aquired_swapchain_image.is_nothing())
......
......@@ -166,6 +166,16 @@ namespace mirrage::util {
template <typename T>
class tracking_ptr;
namespace detail {
struct trackable_data {
void* obj_addr = nullptr;
std::uint32_t revision = 0;
trackable_data() = default;
trackable_data(void* ptr, std::uint32_t rev) : obj_addr(ptr), revision(rev) {}
};
}
template <typename T>
class trackable {
public:
......@@ -178,27 +188,25 @@ namespace mirrage::util {
_obj = std::move(rhs._obj);
_obj_addr = std::move(rhs._obj_addr);
}
~trackable() {
if(_obj_addr) {
*_obj_addr = nullptr;
}
}
~trackable() { reset(); }
auto& operator=(std::unique_ptr<T> obj) {
_obj = std::move(obj);
if(_obj_addr) {
*_obj_addr = _obj.get();
_obj_addr->obj_addr = _obj.get();
_obj_addr->revision++;
}
return *this;
}
void reset() {
auto reset() {
if(_obj_addr) {
*_obj_addr = nullptr;
_obj_addr->obj_addr = nullptr;
_obj_addr->revision++;
}
_obj.reset();
return std::move(_obj);
}
auto create_ptr() -> tracking_ptr<T>;
......@@ -235,12 +243,12 @@ namespace mirrage::util {
template <typename>
friend class tracking_ptr;
std::unique_ptr<T> _obj;
std::shared_ptr<void*> _obj_addr;
std::unique_ptr<T> _obj;
std::shared_ptr<detail::trackable_data> _obj_addr;
auto _get_obj_addr() {
if(!_obj_addr) {
_obj_addr = std::make_shared<void*>(_obj.get());
_obj_addr = std::make_shared<detail::trackable_data>(_obj.get(), 0);
}
return _obj_addr;
......@@ -256,29 +264,42 @@ namespace mirrage::util {
class tracking_ptr {
public:
tracking_ptr() = default;
tracking_ptr(trackable<T>& t) : _trackable(t._get_obj_addr()) {}
tracking_ptr(trackable<T>& t)
: _trackable(t._get_obj_addr()), _last_seen_revision(_trackable ? _trackable->revision : 0) {}
tracking_ptr(const tracking_ptr<T>& t) = default;
tracking_ptr(tracking_ptr<T>&& t) = default;
tracking_ptr& operator=(const tracking_ptr<T>& t) = default;
tracking_ptr& operator=(tracking_ptr<T>&& t) = default;
template <typename I, typename = std::enable_if_t<!std::is_same_v<I, T>>>
explicit tracking_ptr(tracking_ptr<I> t)
: _trackable(t._trackable)
, _caster(+[](void* ptr) { return dynamic_cast<T*>(static_cast<I*>(ptr)); })
, _last_seen_revision(_trackable ? _trackable->revision : 0) {
INVARIANT(t._caster == nullptr, "Casting tracking_ptrs can't be nested! Nice try though.");
}
template <typename I>
explicit tracking_ptr(tracking_ptr<I> t) : _trackable(t._trackable) {
if
constexpr(!std::is_base_of_v<I, T>) {
static_assert(
std::is_base_of_v<T, I>,
"The pointer types I and T don't seem to be related! I has to be either the "
"base class of T of be derived from it.");
auto modified(T* last_seen) {
if(!_trackable) {
return last_seen == nullptr ? false : true;
}
INVARIANT(t._caster == nullptr,
"Casting tracking_ptrs can't be nested! Nice try though.");
auto current_revision = _trackable->revision;
if(_last_seen_revision != current_revision || last_seen == nullptr) {
DEBUG("Modified " << _last_seen_revision << " != " << current_revision);
_last_seen_revision = current_revision;
return true;
}
_caster = +[](void* ptr) { return dynamic_cast<T*>(static_cast<I*>(ptr)); };
}
return false;
}
auto get() -> T* {
if(!_trackable)
return nullptr;
auto ptr = *_trackable;
auto ptr = _trackable->obj_addr;
if(_caster)
return _caster(ptr);
......@@ -321,8 +342,9 @@ namespace mirrage::util {
using Caster = T* (*) (void*);
std::shared_ptr<void*> _trackable;
Caster _caster = nullptr;
std::shared_ptr<detail::trackable_data> _trackable;
Caster _caster = nullptr;
std::uint32_t _last_seen_revision = 0;
};
template <typename T>
......
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