Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RenderingEndPoint #1147

Draft
wants to merge 26 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion frontend/resources/include/ImagePresentationEntryPoints.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "EntryPoint.h"
#include "FrontendResource.h"
#include "ImagePresentationSink.h"

#include <any>
#include <functional>
Expand All @@ -34,8 +35,14 @@ struct ImagePresentationEntryPoints {
std::function<bool(std::string const&, std::string const&)> rename_entry_point;
std::function<void()> clear_entry_points;

std::function<bool(ImagePresentationSink const&)> add_sink;
std::function<bool(std::string const&)> remove_sink;

std::function<bool(std::string const&, std::string const&)> bind_sink_entry_point;
std::function<bool(std::string const&, std::string const&)> unbind_sink_entry_point;

// services may also subscribe to entry point changes to get notified when entry points get added/removed
enum class SubscriptionEvent { Add, Remove, Rename, Clear };
enum class SubscriptionEvent { Add, Remove, Rename, Clear, AddSink, RemoveSink, BindSink, UnbindSink };

using SubscriberFunction =
std::function<void(frontend_resources::ImagePresentationEntryPoints::SubscriptionEvent const&,
Expand Down
1 change: 1 addition & 0 deletions frontend/services/gui/src/GUIManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "widgets/DefaultStyle.h"
#include "windows/HotkeyEditor.h"
#include "windows/PerformanceMonitor.h"
#include "windows/RenderingEndPoint.h"


using namespace megamol::gui;
Expand Down
5 changes: 5 additions & 0 deletions frontend/services/gui/src/GUIManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,11 @@ class GUIManager {
return this->render_backend.GetImage();
}


std::vector<megamol::frontend_resources::ImagePresentationEntryPoints::SubscriberFunction> GetSubscribers() {
return std::vector<megamol::frontend_resources::ImagePresentationEntryPoints::SubscriberFunction>();
}

///////// SET ///////////

/**
Expand Down
6 changes: 6 additions & 0 deletions frontend/services/gui/src/GUI_Service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,12 @@ void GUI_Service::setRequestedResources(std::vector<FrontendResource> resources)
megamol::core::utility::log::Log::DefaultLog.WriteInfo(
"GUI_Service: error adding graph entry point ... image presentation service rejected GUI Service.");
}
{
auto subs = m_gui->GetSubscribers();
for (auto const& sub : subs) {
image_presentation.subscribe_to_entry_point_changes(sub);
}
}

m_exec_lua = const_cast<megamol::frontend_resources::common_types::lua_func_type*>(
&frontend_resources->get<frontend_resources::common_types::lua_func_type>());
Expand Down
3 changes: 2 additions & 1 deletion frontend/services/gui/src/windows/AbstractWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ class AbstractWindow {
WINDOW_ID_HOTKEYEDITOR = 4,
WINDOW_ID_TRANSFER_FUNCTION = 5,
WINDOW_ID_CONFIGURATOR = 6,
WINDOW_ID_LOGCONSOLE = 7
WINDOW_ID_LOGCONSOLE = 7,
WINDOW_ID_RENDERING_ENDPOINT = 8
};

struct BasicConfig {
Expand Down
76 changes: 76 additions & 0 deletions frontend/services/gui/src/windows/RenderingEndPoint.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#include "RenderingEndPoint.h"


megamol::gui::RenderingEndPoint::RenderingEndPoint(std::string const& window_name)
: AbstractWindow(window_name, AbstractWindow::WINDOW_ID_RENDERING_ENDPOINT) {
sink_.name = window_name;
sink_.present_images = std::bind(&RenderingEndPoint::PresentImageCB, this, std::placeholders::_1);
}


//void megamol::gui::RenderingEndPoint::SetTexture(GLuint texture, uint32_t x, uint32_t y) {
// tex_ = reinterpret_cast<ImTextureID>(static_cast<intptr_t>(texture));
// size_ = ImVec2(x, y);
//}


bool megamol::gui::RenderingEndPoint::Draw() {
static const char* current_item = nullptr;
megamol::frontend::ImagePresentation_Service::EntryPointRenderFunctions entry_point;
/*if (ImGui::BeginMainMenuBar()) {


ImGui::EndMainMenuBar();
}*/

auto& img_pres_ep_resource_ptr = frontend_resources->get<frontend_resources::ImagePresentationEntryPoints>();

bool isSelected = false;
if (ImGui::BeginCombo("Views", current_item)) {
for (auto const& item : entry_points_) {
if (ImGui::Selectable(item.first.c_str(), &isSelected)) {
if (current_item != nullptr) {
img_pres_ep_resource_ptr.unbind_sink_entry_point(this->Name(), item.first);
}
current_item = item.first.c_str();
entry_point = item.second;
img_pres_ep_resource_ptr.bind_sink_entry_point(this->Name(), item.first);
}
}
ImGui::EndCombo();
}

/*ImGui::Text("RenderEndPoint");
ImGui::Spacing();*/

//entry_point
if (current_item != nullptr) {
for (auto& image : images_) {
ImGui::Image(image.referenced_image_handle, ImVec2{(float)image.size.width, (float)image.size.height},
ImVec2(0, 1), ImVec2(1, 0));
}

//auto ep = img_pres_ep_resource_ptr.get_entry_point(current_item);
//if (ep.has_value()) {
// frontend_resources::EntryPoint& ep_v = ep.value();

// /*ep_v.entry_point_data->update();

// ep_v.execute(ep_v.modulePtr, ep_v.entry_point_resources, ep_v.execution_result_image);*/

// ImGui::Image(ep_v.execution_result_image.referenced_image_handle,
// ImVec2{(float)ep_v.execution_result_image.size.width, (float)ep_v.execution_result_image.size.height},
// ImVec2(0, 1), ImVec2(1, 0));
// //ImGui::Image(tex_, size_, ImVec2(0, 1), ImVec2(1, 0));
//}
}
/*if (ImGui::Begin("RenderingEndPoint")) {
ImGui::Text("RenderEndPoint");
ImGui::Spacing();

ImGui::Image(tex_, size_, ImVec2(0, 1), ImVec2(1, 0));
}
ImGui::End();*/

return true;
}
73 changes: 73 additions & 0 deletions frontend/services/gui/src/windows/RenderingEndPoint.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#pragma once

#include <map>
#include <stdint.h>

#include <glad/gl.h>

#include "AbstractWindow.h"

#include "ImagePresentationEntryPoints.h"
#include "ImagePresentation_Service.hpp"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This dependency between GUI (GUI Service) and Image Presentation Service may lead to problems. For cleaner separation of code it will be cleaner to pull the dependencies from ImagePresentation_Service.hpp into a separate header or otherwise restructure the affected code.


namespace megamol::gui {
class RenderingEndPoint : public AbstractWindow {
public:
std::vector<std::string> requested_lifetime_resources() const override {
auto res = AbstractWindow::requested_lifetime_resources();
res.push_back("ImagePresentationEntryPoints");
return res;
}

void setRequestedResources(std::shared_ptr<frontend_resources::FrontendResourcesMap> const& resources) override {
AbstractWindow::setRequestedResources(resources);
auto& img_pres_ep_resource_ptr = frontend_resources->get<frontend_resources::ImagePresentationEntryPoints>();

auto sub_func = [&](frontend_resources::ImagePresentationEntryPoints::SubscriptionEvent const& event,
std::vector<std::any> const& args) -> void {
switch (event) {
case frontend_resources::ImagePresentationEntryPoints::SubscriptionEvent::Add: {
entry_points_.insert(std::make_pair(std::any_cast<std::string>(args[0]),
std::any_cast<frontend::ImagePresentation_Service::EntryPointRenderFunctions>(args[1])));
} break;
case frontend_resources::ImagePresentationEntryPoints::SubscriptionEvent::Remove: {
entry_points_.erase(std::any_cast<std::string>(args[0]));
} break;
case frontend_resources::ImagePresentationEntryPoints::SubscriptionEvent::Rename: {
auto func = entry_points_[std::any_cast<std::string>(args[0])];
entry_points_.erase(std::any_cast<std::string>(args[0]));
entry_points_.insert(std::make_pair(std::any_cast<std::string>(args[1]), func));
} break;
case frontend_resources::ImagePresentationEntryPoints::SubscriptionEvent::Clear:
default:
break;
}
};

img_pres_ep_resource_ptr.subscribe_to_entry_point_changes(sub_func);
img_pres_ep_resource_ptr.add_sink(sink_);
}

explicit RenderingEndPoint(const std::string& window_name);

//virtual ~RenderingEndPoint() {
// auto& img_pres_ep_resource_ptr = frontend_resources->get<frontend_resources::ImagePresentationEntryPoints>();
// img_pres_ep_resource_ptr.remove_sink(sink_.name);
//}

//void SetTexture(GLuint texture, uint32_t x, uint32_t y);

bool Draw() override;

void PresentImageCB(std::vector<frontend_resources::ImageWrapper> const& images) {
images_ = images;
}

private:
/*ImTextureID tex_;
ImVec2 size_;*/
std::map<std::string, frontend::ImagePresentation_Service::EntryPointRenderFunctions> entry_points_;
std::vector<frontend_resources::ImageWrapper> images_;
frontend_resources::ImagePresentationSink sink_;
};
} // namespace megamol::gui
2 changes: 2 additions & 0 deletions frontend/services/gui/src/windows/WindowCollection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "LogConsole.h"
#include "ParameterList.h"
#include "PerformanceMonitor.h"
#include "RenderingEndPoint.h"
#include "TransferFunctionEditor.h"


Expand All @@ -27,6 +28,7 @@ WindowCollection::WindowCollection() : windows() {
this->windows.emplace_back(std::make_shared<PerformanceMonitor>("Performance Metrics"));
this->windows.emplace_back(
std::make_shared<Configurator>("Configurator", this->GetWindow<TransferFunctionEditor>()));
this->windows.emplace_back(std::make_shared<RenderingEndPoint>("Rendering Endpoint"));
// Requires Configurator and TFEditor to be added before
this->add_parameter_window("Parameters", AbstractWindow::WINDOW_ID_MAIN_PARAMETERS);

Expand Down
1 change: 1 addition & 0 deletions frontend/services/gui/src/windows/WindowCollection.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <functional>
#include <map>
#include <string>
#include <unordered_map>
#include <vector>


Expand Down
70 changes: 64 additions & 6 deletions frontend/services/image_presentation/ImagePresentation_Service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,23 @@ bool ImagePresentation_Service::init(const Config& config) {
};
m_entry_points_registry_resource.get_entry_point = [&](auto const& name) { return get_entry_point(name); };

m_entry_points_registry_resource.add_sink = [&](auto const& sink) {
return add_sink(sink) && tell_subscribers(ev::AddSink, {sink});
};

m_entry_points_registry_resource.remove_sink = [&](auto const& name) {
return remove_sink(name) && tell_subscribers(ev::RemoveSink, {name});
};

m_entry_points_registry_resource.bind_sink_entry_point = [&](std::string const& sink_name,
std::string const& ep_name) {
return bind_sink_to_ep(sink_name, ep_name) && tell_subscribers(ev::BindSink, {sink_name, ep_name});
};
m_entry_points_registry_resource.unbind_sink_entry_point = [&](std::string const& sink_name,
std::string const& ep_name) {
return unbind_sink_to_ep(sink_name, ep_name) && tell_subscribers(ev::UnbindSink, {sink_name, ep_name});
};

this->m_providedResourceReferences = {
{"ImagePresentationEntryPoints", m_entry_points_registry_resource}, // used by MegaMolGraph to set entry points
{"EntryPointToPNG_ScreenshotTrigger", m_entrypointToPNG_trigger},
Expand Down Expand Up @@ -203,18 +220,20 @@ void ImagePresentation_Service::PresentRenderedImages() {
// this way sinks can access the current fbo size as previous_state
m_global_framebuffer_events.clear();

// pull result images into separate list
static std::vector<ImageWrapper> wrapped_images;
wrapped_images.clear();
wrapped_images.reserve(m_entry_points.size());
// pull result images into separate lists
std::unordered_map<std::string, std::vector<ImageWrapper>> sink_img_map;
sink_img_map.reserve(m_presentation_sinks.size());

// rendering results are presented in order of execution of entry points
for (auto& entry : m_entry_points) {
wrapped_images.push_back(entry.execution_result_image);
auto const& sink_list = ep_sink_map[entry.moduleName];
for (auto const& sink : sink_list) {
sink_img_map[sink].push_back(entry.execution_result_image);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about the details but it might lead to many GL texture / Byte texture copy operations when putting ImageWrapper execution_result_image in different places. I believe the initial goal for the ImageWrapper was to have a lightweight abstraction over GL/Byte textures with the option to transform one into the other (texture down/upload). It may be that the ImageWrapper copy constructor also copies textures/vectors internally, depending on whether the held texture is only referenced or actually owned.

}
}

for (auto& sink : m_presentation_sinks) {
sink.present_images(wrapped_images);
sink.present_images(sink_img_map[sink.name]);
}
}

Expand Down Expand Up @@ -331,6 +350,8 @@ bool ImagePresentation_Service::add_entry_point(std::string const& name, EntryPo
// ensure sorting of entry points according to priorities
set_entry_point_priority(name, 0);

bind_sink_to_ep("GLFW Window Presentation Sink", name);

return true;
}

Expand All @@ -352,6 +373,8 @@ bool ImagePresentation_Service::set_entry_point_priority(std::string const& name

bool ImagePresentation_Service::remove_entry_point(std::string const& name) {

ep_sink_map.erase(name);

m_entry_points.remove_if([&](auto& entry) { return entry.moduleName == name; });

return true;
Expand All @@ -368,12 +391,47 @@ bool ImagePresentation_Service::rename_entry_point(std::string const& oldName, s

entry_it->moduleName = newName;

auto l = ep_sink_map[oldName];
ep_sink_map.erase(oldName);
ep_sink_map[newName] = l;

return true;
}

bool ImagePresentation_Service::clear_entry_points() {
m_entry_points.clear();

ep_sink_map.clear();

return true;
}

bool ImagePresentation_Service::add_sink(ImagePresentationSink const& sink) {
m_presentation_sinks.push_back(sink);
return true;
}

bool ImagePresentation_Service::remove_sink(std::string const& name) {
m_presentation_sinks.remove_if([&name](auto const& entry) { return entry.name == name; });
for (auto& [key, list] : ep_sink_map) {
list.remove(name);
}
return true;
}

bool ImagePresentation_Service::bind_sink_to_ep(std::string const& sink_name, std::string const& ep_name) {
auto& sink_list = ep_sink_map[ep_name];
if (std::find(sink_list.begin(), sink_list.end(), sink_name) == sink_list.end()) {
sink_list.push_back(sink_name);
}

return true;
}

bool ImagePresentation_Service::unbind_sink_to_ep(std::string const& sink_name, std::string const& ep_name) {
auto& sink_list = ep_sink_map[ep_name];
sink_list.remove(sink_name);

return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ class ImagePresentation_Service final : public AbstractFrontendService {
bool remove_entry_point(std::string const& name);
bool rename_entry_point(std::string const& oldName, std::string const& newName);
bool clear_entry_points();
bool add_sink(ImagePresentationSink const& sink);
bool remove_sink(std::string const& name);
bool bind_sink_to_ep(std::string const& sink_name, std::string const& ep_name);
bool unbind_sink_to_ep(std::string const& sink_name, std::string const& ep_name);

void subscribe_to_entry_point_changes(
frontend_resources::ImagePresentationEntryPoints::SubscriberFunction const& subscriber);
Expand Down Expand Up @@ -135,6 +139,8 @@ class ImagePresentation_Service final : public AbstractFrontendService {
void fill_lua_callbacks();

std::function<bool(std::string const&, std::string const&)> m_entrypointToPNG_trigger;

std::unordered_map<std::string, std::list<std::string>> ep_sink_map;
};

} // namespace frontend
Expand Down
2 changes: 1 addition & 1 deletion plugins/optix_hpg/src/optix/Context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ megamol::optix_hpg::Context::Context(frontend_resources::CUDA_Context const& ctx
_module_options.maxRegisterCount = OPTIX_COMPILE_DEFAULT_MAX_REGISTER_COUNT;
#ifdef DEBUG
_module_options.optLevel = OPTIX_COMPILE_OPTIMIZATION_LEVEL_0;
_module_options.debugLevel = OPTIX_COMPILE_DEBUG_LEVEL_LINEINFO;
_module_options.debugLevel = OPTIX_COMPILE_DEBUG_LEVEL_MODERATE;
#else
_module_options.optLevel = OPTIX_COMPILE_OPTIMIZATION_LEVEL_3;
_module_options.debugLevel = OPTIX_COMPILE_DEBUG_LEVEL_NONE;
Expand Down