Skip to content

Commit

Permalink
Zephyr: Renderer: begin material system (early WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
fleroviux committed May 22, 2024
1 parent 803b32f commit c81053b
Show file tree
Hide file tree
Showing 12 changed files with 89 additions and 74 deletions.
4 changes: 2 additions & 2 deletions app/next/src/gltf_loader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -378,11 +378,11 @@ namespace zephyr {
if(node_json.contains("mesh")) {
Mesh& mesh = m_meshes[node_json["mesh"].get<size_t>()];
if(mesh.primitives.size() == 1u) {
node->CreateComponent<MeshComponent>(mesh.primitives[0].geometry);
node->CreateComponent<MeshComponent>(mesh.primitives[0].geometry, std::shared_ptr<Material>{});
} else {
for(size_t i = 0; i < mesh.primitives.size(); i++) {
std::shared_ptr<SceneNode> primitive_node = node->CreateChild(fmt::format("{}#{}", name, i));
primitive_node->CreateComponent<MeshComponent>(mesh.primitives[i].geometry);
primitive_node->CreateComponent<MeshComponent>(mesh.primitives[i].geometry, std::shared_ptr<Material>{});
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions app/next/src/main_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#include "main_window.hpp"

static const bool enable_validation_layers = true;
static const bool benchmark_scene_size = true;
static const bool benchmark_scene_size = false;

namespace zephyr {

Expand Down Expand Up @@ -268,7 +268,7 @@ namespace zephyr {
for(int y = -grid_size / 2; y < grid_size / 2; y++) {
for(int z = -grid_size / 2; z < grid_size / 2; z++) {
std::shared_ptr<SceneNode> cube = m_scene_root->CreateChild("Cube");
cube->CreateComponent<MeshComponent>(cube_geometry);
cube->CreateComponent<MeshComponent>(cube_geometry, std::shared_ptr<Material>{});
cube->GetTransform().GetPosition() = {(f32)x, (f32)y, (f32)-z};
cube->GetTransform().GetScale() = {0.1, 0.1, 0.1};
}
Expand Down
3 changes: 1 addition & 2 deletions zephyr/common/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@

set(SOURCES
src/panic.cpp
src/uid.cpp
)

set(HEADERS
Expand All @@ -11,6 +10,7 @@ set(HEADERS_PUBLIC
include/zephyr/bit.hpp
include/zephyr/event.hpp
include/zephyr/float.hpp
include/zephyr/hash.hpp
include/zephyr/integer.hpp
include/zephyr/literal.hpp
include/zephyr/meta.hpp
Expand All @@ -19,7 +19,6 @@ set(HEADERS_PUBLIC
include/zephyr/panic.hpp
include/zephyr/punning.hpp
include/zephyr/result.hpp
include/zephyr/uid.hpp
include/zephyr/vector_n.hpp
)

Expand Down
15 changes: 15 additions & 0 deletions zephyr/common/include/zephyr/hash.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

#pragma once

#include <cstddef>
#include <functional>

namespace zephyr {

template<typename T>
inline void hash_combine(std::size_t& s, const T& v) {
std::hash<T> h;
s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2);
}

} // namespace zephyr
39 changes: 0 additions & 39 deletions zephyr/common/include/zephyr/uid.hpp

This file was deleted.

8 changes: 0 additions & 8 deletions zephyr/common/src/uid.cpp

This file was deleted.

1 change: 1 addition & 0 deletions zephyr/renderer/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ set(HEADERS_PUBLIC
include/zephyr/renderer/component/mesh.hpp
include/zephyr/renderer/engine/geometry_cache.hpp
include/zephyr/renderer/resource/geometry.hpp
include/zephyr/renderer/resource/material.hpp
include/zephyr/renderer/resource/resource.hpp
include/zephyr/renderer/vulkan/vulkan_instance.hpp
include/zephyr/renderer/vulkan/vulkan_physical_device.hpp
Expand Down
4 changes: 3 additions & 1 deletion zephyr/renderer/include/zephyr/renderer/component/mesh.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@
#pragma once

#include <zephyr/renderer/resource/geometry.hpp>
#include <zephyr/renderer/resource/material.hpp>
#include <zephyr/scene/component.hpp>
#include <memory>

namespace zephyr {

struct MeshComponent : Component {
MeshComponent() = default;
MeshComponent(std::shared_ptr<Geometry> geometry) : geometry{std::move(geometry)} {}
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;
};

} // namespace zephyr
12 changes: 12 additions & 0 deletions zephyr/renderer/include/zephyr/renderer/resource/material.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

#pragma once

#include <zephyr/renderer/resource/resource.hpp>

namespace zephyr {

class Material : public Resource {
public:
};

} // namespace zephyr
44 changes: 27 additions & 17 deletions zephyr/renderer/src/backend/opengl/render_backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ namespace zephyr {
glCreateBuffers(1u, &m_gl_draw_count_out_ac);
glNamedBufferStorage(m_gl_draw_count_out_ac, sizeof(GLuint), nullptr, 0);

f32 material_data[] = {
1.0, 0.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0
};
glCreateBuffers(1u, &m_gl_material_data_buffer);
glNamedBufferStorage(m_gl_material_data_buffer, sizeof(material_data), material_data, 0);

glEnable(GL_DEPTH_TEST);

m_render_geometry_manager = std::make_unique<OpenGLRenderGeometryManager>();
Expand All @@ -42,6 +50,7 @@ namespace zephyr {
void OpenGLRenderBackend::DestroyContext() {
m_render_geometry_manager.reset();

glDeleteBuffers(1u, &m_gl_material_data_buffer);
glDeleteBuffers(1u, &m_gl_draw_count_out_ac);
glDeleteBuffers(1u, &m_gl_draw_count_ubo);
glDeleteBuffers(1u, &m_gl_camera_ubo);
Expand Down Expand Up @@ -74,26 +83,17 @@ namespace zephyr {
}

void OpenGLRenderBackend::Render(const RenderCamera& render_camera, std::span<const RenderObject> render_objects) {
// TODO(fleroviux): implement render bundle key more cleanly
using RenderBundleKey = u64;

std::unordered_map<RenderBundleKey, std::vector<RenderBundleItem>> render_bundles;

for(const RenderObject& render_object : render_objects) {
// TODO(fleroviux): get rid of unsafe size_t to u32 conversion.
// TODO(fleroviux): deal with non-indexed geometries
auto render_geometry = dynamic_cast<OpenGLRenderGeometry*>(render_object.render_geometry);
RenderBundleKey render_bundle_key = render_geometry->GetLayout().key;
if(render_geometry->GetNumberOfIndices() > 0u) {
render_bundle_key |= 0x8000'0000'0000'0000ull;
}
render_bundles[render_bundle_key].emplace_back(render_object.local_to_world, (u32) render_geometry->GetGeometryID());
RenderBundleKey render_bundle_key{};
render_bundle_key.uses_ibo = render_geometry->GetNumberOfIndices();
render_bundle_key.geometry_layout = render_geometry->GetLayout().key;
render_bundles[render_bundle_key].emplace_back(render_object.local_to_world, (u32)render_geometry->GetGeometryID(), (u32)0u);
}

// TODO(fleroviux): apply Z-sorting on the render bundles here

// ----------------------------------------------------------------

glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

Expand All @@ -105,7 +105,6 @@ namespace zephyr {

for(const auto& [key, render_bundle] : render_bundles) {
const size_t render_bundle_size = render_bundle.size();
const bool uses_ibo = key & 0x8000'0000'0000'0000ull;

for(size_t base_draw = 0u; base_draw < render_bundle_size; base_draw += k_max_draws_per_draw_call) {
const u32 number_of_draws = std::min<size_t>(render_bundle_size - base_draw, k_max_draws_per_draw_call);
Expand Down Expand Up @@ -136,12 +135,13 @@ namespace zephyr {
{
glUseProgram(m_gl_draw_program);

glBindVertexArray(m_render_geometry_manager->GetVAOFromLayout(RenderGeometryLayout{key}));
glBindVertexArray(m_render_geometry_manager->GetVAOFromLayout(RenderGeometryLayout{key.geometry_layout}));
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_gl_draw_list_command_ssbo);
glBindBuffer(GL_PARAMETER_BUFFER, m_gl_draw_count_out_ac);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2u, m_gl_material_data_buffer);

glMemoryBarrier(GL_COMMAND_BARRIER_BIT | GL_ATOMIC_COUNTER_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT);
if(uses_ibo) {
if(key.uses_ibo) {
glMultiDrawElementsIndirectCount(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr, 0u, (GLsizei)number_of_draws, 6u * sizeof(u32));
} else {
glMultiDrawArraysIndirectCount(GL_TRIANGLES, nullptr, 0u, (GLsizei)number_of_draws, 6u * sizeof(u32));
Expand All @@ -150,6 +150,7 @@ namespace zephyr {
glBindVertexArray(0u);
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0u);
glBindBuffer(GL_PARAMETER_BUFFER, 0u);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2u, 0u);
}
}
}
Expand All @@ -170,6 +171,7 @@ namespace zephyr {
struct RenderBundleItem {
mat4 local_to_world;
uint geometry_id;
uint material_id;
};
struct DrawCommandWithRenderBundleItemID {
Expand All @@ -195,12 +197,14 @@ namespace zephyr {
layout(location = 2) in vec2 a_uv;
layout(location = 3) in vec3 a_color;
flat out uint fv_material_id;
out vec3 v_normal;
out vec3 v_color;
void main() {
uint render_bundle_item_id = rb_command_buffer[gl_DrawID].render_bundle_item_id;
fv_material_id = rb_render_bundle_items[render_bundle_item_id].material_id;
v_normal = a_normal;
v_color = a_color;
gl_Position = u_projection * u_view * rb_render_bundle_items[render_bundle_item_id].local_to_world * vec4(a_position, 1.0);
Expand All @@ -210,13 +214,19 @@ namespace zephyr {
GLuint frag_shader = CreateShader(R"(
#version 460 core
layout(std430, binding = 2) readonly buffer MaterialBuffer {
vec4 rb_material_color[];
};
layout(location = 0) out vec4 f_frag_color;
flat in uint fv_material_id;
in vec3 v_normal;
in vec3 v_color;
void main() {
f_frag_color = vec4(v_normal * 0.5 + 0.5, 1.0);
vec4 material_color = rb_material_color[fv_material_id];
f_frag_color = vec4(v_normal * 0.25 + 0.25 + material_color.rgb * 0.5, 1.0);
}
)", GL_FRAGMENT_SHADER);

Expand Down
27 changes: 25 additions & 2 deletions zephyr/renderer/src/backend/opengl/render_backend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#pragma once

#include <zephyr/renderer/backend/render_backend.hpp>
#include <zephyr/hash.hpp>
#include <zephyr/panic.hpp>
#include <GL/glew.h>
#include <GL/gl.h>
Expand All @@ -15,6 +16,15 @@ namespace zephyr {

class OpenGLRenderBackend final : public RenderBackend {
public:
struct RenderBundleKey {
bool uses_ibo;
u32 geometry_layout;

[[nodiscard]] bool operator==(const RenderBundleKey& other) const {
return uses_ibo == other.uses_ibo && geometry_layout == other.geometry_layout;
}
};

explicit OpenGLRenderBackend(SDL_Window* sdl2_window);

void InitializeContext() override;
Expand All @@ -32,10 +42,11 @@ namespace zephyr {

private:
struct RenderBundleItem {
RenderBundleItem(const Matrix4& local_to_world, u32 draw_command_id) : local_to_world{local_to_world}, draw_command_id{draw_command_id} {}
RenderBundleItem(const Matrix4& local_to_world, u32 draw_command_id, u32 material_id) : local_to_world{local_to_world}, draw_command_id{draw_command_id}, material_id{material_id} {}
Matrix4 local_to_world;
u32 draw_command_id;
u32 padding[3]; // Padding for std430 buffer layout
u32 material_id;
u32 padding[2]; // Padding for std430 buffer layout
};

static constexpr u32 k_max_draws_per_draw_call = 16384;
Expand All @@ -56,6 +67,8 @@ namespace zephyr {
GLuint m_gl_draw_count_ubo{};
GLuint m_gl_draw_count_out_ac{};

GLuint m_gl_material_data_buffer{};

std::unique_ptr<OpenGLRenderGeometryManager> m_render_geometry_manager{};
};

Expand All @@ -64,3 +77,13 @@ namespace zephyr {
}

} // namespace zephyr

template<>
struct std::hash<zephyr::OpenGLRenderBackend::RenderBundleKey> {
[[nodiscard]] std::size_t operator()(const zephyr::OpenGLRenderBackend::RenderBundleKey& key) const noexcept {
size_t h = 0;
zephyr::hash_combine(h, key.uses_ibo);
zephyr::hash_combine(h, key.geometry_layout);
return h;
}
};
2 changes: 1 addition & 1 deletion zephyr/renderer/src/backend/opengl/render_geometry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ namespace zephyr {
void WriteIBO(std::span<const u8> data) {
// TODO(fleroviux): this does not protect against writing into neighbouring allocations.
if(!m_ibo) {
ZEPHYR_PANIC("Attempted to write IBO of non-indexed render geometry");
ZEPHYR_PANIC("Attempted to write IBO of non-uses_ibo render geometry");
}
m_ibo->Write(data, m_ibo_allocation.base_element);
}
Expand Down

0 comments on commit c81053b

Please sign in to comment.