Skip to content

Commit

Permalink
A bunch of hacky optimizations...
Browse files Browse the repository at this point in the history
  • Loading branch information
fleroviux committed May 25, 2024
1 parent 979414c commit 6ff09a8
Show file tree
Hide file tree
Showing 9 changed files with 169 additions and 35 deletions.
2 changes: 1 addition & 1 deletion app/next/src/main_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ namespace zephyr {

void MainWindow::RenderFrame() {
m_scene->UpdateTransforms();
m_render_engine->RenderScene(m_scene->GetRoot());
m_render_engine->RenderScene(m_scene.get());
m_frame++;

UpdateFramesPerSecondCounter();
Expand Down
3 changes: 3 additions & 0 deletions zephyr/renderer/include/zephyr/renderer/component/mesh.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@

namespace zephyr {

class SceneNode;

struct MeshComponent : Component {
MeshComponent() = default;
MeshComponent(std::shared_ptr<Geometry> geometry, std::shared_ptr<Material> material) : geometry{std::move(geometry)}, material{std::move(material)} {}

std::shared_ptr<Geometry> geometry;
std::shared_ptr<Material> material;
SceneNode* owner;
};

} // namespace zephyr
4 changes: 2 additions & 2 deletions zephyr/renderer/include/zephyr/renderer/render_engine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include <zephyr/renderer/backend/render_backend.hpp>
#include <zephyr/renderer/engine/geometry_cache.hpp>
#include <zephyr/renderer/resource/geometry.hpp>
#include <zephyr/scene/node.hpp>
#include <zephyr/scene/scene.hpp>
#include <atomic>
#include <semaphore>
#include <thread>
Expand All @@ -18,7 +18,7 @@ namespace zephyr {
explicit RenderEngine(std::unique_ptr<RenderBackend> render_backend);
~RenderEngine();

void RenderScene(SceneNode* scene_root);
void RenderScene(Scene* scene);

private:
void CreateRenderThread();
Expand Down
2 changes: 2 additions & 0 deletions zephyr/renderer/src/backend/opengl/render_backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ namespace zephyr {
glEnable(GL_DEPTH_TEST);

m_render_geometry_manager = std::make_unique<OpenGLRenderGeometryManager>();

SDL_GL_SetSwapInterval(0);
}

void OpenGLRenderBackend::DestroyContext() {
Expand Down
75 changes: 49 additions & 26 deletions zephyr/renderer/src/render_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace zephyr {
JoinRenderThread();
}

void RenderEngine::RenderScene(SceneNode* scene_root) {
void RenderEngine::RenderScene(Scene* scene) {
// Wait for the render thread to complete reading the internal render structures.
m_render_thread_semaphore.acquire();

Expand All @@ -26,33 +26,56 @@ namespace zephyr {
// Traverse the scene and update any data structures (such as render lists and resource caches) needed to render the frame.
m_game_thread_render_objects.clear();
m_render_camera[1] = {};
scene_root->Traverse([&](SceneNode* node) -> bool {
if(!node->IsVisible()) return false;

if(node->HasComponent<MeshComponent>()) {
const MeshComponent& mesh_component = node->GetComponent<MeshComponent>();
const auto& geometry = mesh_component.geometry;

if(geometry) {
m_geometry_cache.UpdateGeometry(geometry.get());

m_game_thread_render_objects.push_back({
.local_to_world = node->GetTransform().GetWorld(),
.geometry = geometry.get()
});
}
}

// TODO(fleroviux): think of a better way to mark the camera we actually want to use.
if(node->HasComponent<PerspectiveCameraComponent>()) {
const PerspectiveCameraComponent& camera_component = node->GetComponent<PerspectiveCameraComponent>();
m_render_camera[1].projection = camera_component.GetProjectionMatrix();
m_render_camera[1].view = node->GetTransform().GetWorld().Inverse();
m_render_camera[1].frustum = camera_component.GetFrustum();
// scene->GetRoot()->Traverse([&](SceneNode* node) -> bool {
// if(!node->IsVisible()) return false;
//
// if(node->HasComponent<MeshComponent>()) {
// const MeshComponent& mesh_component = node->GetComponent<MeshComponent>();
// const auto& geometry = mesh_component.geometry;
//
// if(geometry) {
// m_geometry_cache.UpdateGeometry(geometry.get());
//
// m_game_thread_render_objects.push_back({
// .local_to_world = node->GetTransform().GetWorld(),
// .geometry = geometry.get()
// });
// }
// }
//
// // TODO(fleroviux): think of a better way to mark the camera we actually want to use.
// if(node->HasComponent<PerspectiveCameraComponent>()) {
// const PerspectiveCameraComponent& camera_component = node->GetComponent<PerspectiveCameraComponent>();
// m_render_camera[1].projection = camera_component.GetProjectionMatrix();
// m_render_camera[1].view = node->GetTransform().GetWorld().Inverse();
// m_render_camera[1].frustum = camera_component.GetFrustum();
// }
//
// return true;
// });


// TODO: this totally breaks the visibility tree right now
for(MeshComponent* mesh_component : scene->GetMeshNodes()) {
const auto& geometry = mesh_component->geometry;

if(geometry) {
m_geometry_cache.UpdateGeometry(geometry.get());

m_game_thread_render_objects.emplace_back(
mesh_component->owner->GetTransform().GetWorld(),//node->GetTransform().GetWorld(),
geometry.get()
);
}
}

return true;
});
for(SceneNode* node : scene->GetCameraNodes()) {
const PerspectiveCameraComponent& camera_component = node->GetComponent<PerspectiveCameraComponent>();
m_render_camera[1].projection = camera_component.GetProjectionMatrix();
m_render_camera[1].view = node->GetTransform().GetWorld().Inverse();
m_render_camera[1].frustum = camera_component.GetFrustum();
break; // We only handle one camera for now
}

// Signal to the render thread that the next frame is ready
m_caller_thread_semaphore.release();
Expand Down
2 changes: 1 addition & 1 deletion zephyr/scene/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ add_library(zephyr-scene ${SOURCES} ${HEADERS} ${HEADERS_PUBLIC})

target_include_directories(zephyr-scene PRIVATE src)
target_include_directories(zephyr-scene PUBLIC include)
target_link_libraries(zephyr-scene PUBLIC zephyr-common zephyr-math zephyr-cxx-opts)
target_link_libraries(zephyr-scene PUBLIC zephyr-common zephyr-math zephyr-renderer zephyr-cxx-opts)
20 changes: 15 additions & 5 deletions zephyr/scene/include/zephyr/scene/node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,14 @@ namespace zephyr {
void Add(std::shared_ptr<SceneNode> node) {
node->RemoveFromParent();
node->m_parent = this;
node->Traverse([&](SceneNode* child_node){
child_node->m_scene = m_scene;
child_node->MarkTransformAsDirty();
return true;
});
if(m_scene) {
node->Traverse([&](SceneNode *child_node) {
child_node->m_scene = m_scene;
child_node->MarkTransformAsDirty();
return true;
});
}
SignalNodeMounted(node.get());
m_children.push_back(std::move(node));
}

Expand All @@ -75,6 +78,7 @@ namespace zephyr {
}

std::shared_ptr<SceneNode> node_ptr = std::move(*it);
SignalNodeRemoved(node);
node_ptr->m_parent = nullptr;
node->Traverse([](SceneNode* child_node){
child_node->m_scene = nullptr;
Expand Down Expand Up @@ -154,6 +158,7 @@ namespace zephyr {

T* component_raw_ptr = component.get();
m_components[std::type_index{typeid(T)}] = std::move(component);
SignalComponentAdded();
return *component_raw_ptr;
}

Expand All @@ -163,6 +168,7 @@ namespace zephyr {
ZEPHYR_PANIC("Node does not have a component of the type: '{}'", typeid(T).name());
}
m_components.erase(m_components.find(std::type_index{typeid(T)}));
SignalComponentRemoved();
}

private:
Expand All @@ -174,6 +180,10 @@ namespace zephyr {
m_transform.UpdateWorld();
}

void SignalNodeMounted(SceneNode* node);
void SignalNodeRemoved(SceneNode* node);
void SignalComponentAdded();
void SignalComponentRemoved();
void MarkTransformAsDirty();

SceneNode* m_parent{};
Expand Down
71 changes: 71 additions & 0 deletions zephyr/scene/include/zephyr/scene/scene.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@

#pragma once

// UGH this creates a nasty dependency on the renderer
#include <zephyr/renderer/component/camera.hpp>
#include <zephyr/renderer/component/mesh.hpp>

#include <zephyr/scene/node.hpp>
#include <span>
#include <unordered_set>
#include <vector>

Expand All @@ -21,6 +26,14 @@ namespace zephyr {
return m_root_node.get();
}

[[nodiscard]] std::span<SceneNode* const> GetCameraNodes() const {
return m_camera_nodes;
}

[[nodiscard]] std::span<MeshComponent* const> GetMeshNodes() const {
return m_mesh_nodes;
}

void UpdateTransforms() {
for(auto node : m_nodes_with_dirty_transforms) {
node->Traverse([](SceneNode* child_node) {
Expand All @@ -41,8 +54,66 @@ namespace zephyr {
m_nodes_with_dirty_transforms.insert(node);
}

// TODO(fleroviux): also track component add/removal

void SignalNodeMounted(SceneNode* node) {
node->Traverse([this](SceneNode* child_node) {
if(child_node->HasComponent<PerspectiveCameraComponent>()) {
m_camera_nodes.push_back(child_node);
}

if(child_node->HasComponent<MeshComponent>()) {
m_mesh_nodes.push_back(&child_node->GetComponent<MeshComponent>());
child_node->GetComponent<MeshComponent>().owner = child_node;
}
return true;
});
}

void SignalNodeRemoved(SceneNode* node) {
node->Traverse([this](SceneNode* child_node) {
if(child_node->HasComponent<PerspectiveCameraComponent>()) {
m_camera_nodes.erase(std::ranges::find(m_camera_nodes, child_node));
}

if(child_node->HasComponent<MeshComponent>()) {
m_mesh_nodes.erase(std::ranges::find(m_mesh_nodes, &child_node->GetComponent<MeshComponent>()));
}
return true;
});
}

void SignalComponentAdded(SceneNode* node) {
if(node->HasComponent<PerspectiveCameraComponent>() && std::ranges::find(m_camera_nodes, node) == m_camera_nodes.end()) {
m_camera_nodes.push_back(node);
}

if(node->HasComponent<MeshComponent>() && std::ranges::find(m_mesh_nodes, &node->GetComponent<MeshComponent>()) == m_mesh_nodes.end()) {
m_mesh_nodes.push_back(&node->GetComponent<MeshComponent>());
node->GetComponent<MeshComponent>().owner = node;
}
}

void SignalComponentRemoved(SceneNode* node) {
if(!node->HasComponent<PerspectiveCameraComponent>()) {
const auto it = std::ranges::find(m_camera_nodes, node);
if(it != m_camera_nodes.end()) {
m_camera_nodes.erase(it);
}
}

if(!node->HasComponent<MeshComponent>()) {
const auto it = std::ranges::find(m_mesh_nodes, &node->GetComponent<MeshComponent>());
if(it != m_mesh_nodes.end()) {
m_mesh_nodes.erase(it);
}
}
}

std::shared_ptr<SceneNode> m_root_node{};
std::unordered_set<SceneNode*> m_nodes_with_dirty_transforms{};
std::vector<SceneNode*> m_camera_nodes{};
std::vector<MeshComponent*> m_mesh_nodes{};
};

} // namespace zephyr
25 changes: 25 additions & 0 deletions zephyr/scene/src/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,31 @@

namespace zephyr {

void SceneNode::SignalNodeMounted(SceneNode* node) {
if(m_scene) {
m_scene->SignalNodeMounted(node);
}
}

void SceneNode::SignalNodeRemoved(SceneNode* node) {
if(m_scene) {
m_scene->SignalNodeRemoved(node);
}
}

void SceneNode::SignalComponentAdded() {
if(m_scene) {
m_scene->SignalComponentAdded(this);
}
}

void SceneNode::SignalComponentRemoved() {
if(m_scene) {
m_scene->SignalComponentRemoved(this);
}

}

void SceneNode::MarkTransformAsDirty() {
if(m_scene) {
m_scene->MarkSceneNodeTransformAsDirty(this);
Expand Down

0 comments on commit 6ff09a8

Please sign in to comment.