From d204a72b8eaefab381280788a032faad958a94e8 Mon Sep 17 00:00:00 2001 From: David Bauer Date: Thu, 25 Apr 2024 20:21:42 -0700 Subject: [PATCH 1/2] Alignment is now an option in the Config --- CMakeLists.txt | 3 -- README.md | 4 --- src/CMakeLists.txt | 8 ----- src/backstage/alignment.h | 7 ---- src/backstage/buffer.h | 9 +++-- src/backstage/camera.h | 9 +++-- src/backstage/config.h | 3 +- src/backstage/light.h | 9 +++-- src/backstage/material.h | 7 ++-- src/backstage/math.h | 5 +++ src/backstage/mesh.cpp | 47 +++++++++++++------------- src/backstage/mesh.h | 12 ++----- src/backstage/scene.cpp | 71 ++++++++++++++++----------------------- 13 files changed, 79 insertions(+), 115 deletions(-) delete mode 100644 src/backstage/alignment.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f1ccd62..130da57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,9 +13,6 @@ OPTION(STAGE_LOGGING_WARN OFF) OPTION(STAGE_LOGGING_LOG OFF) OPTION(STAGE_LOGGING_OFF OFF) -OPTION(STAGE_API_USAGE_OPENGL OFF) -OPTION(STAGE_API_USAGE_METAL OFF) - add_subdirectory(dependencies) add_subdirectory(src) diff --git a/README.md b/README.md index 0fa94a4..b2e6358 100644 --- a/README.md +++ b/README.md @@ -183,10 +183,6 @@ cmake --build build -j ### Build Options The CMake build offers several options to customize the build: -**Data Alignment** -* `STAGE_API_USAGE_OPENGL` - Stage will try to align types to 16 bytes -* `STAGE_API_USAGE_METAL` - Stage will perform no explicit data alignment - **Logging** * `STAGE_LOGGING_WARN` - Turn on warning log messages. * `STAGE_LOGGING_LOG` - Turn on all log messages. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8870e33..76fc5d6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -42,13 +42,6 @@ if (STAGE_LOGGING_OFF) set (STAGE_COMPILE_DEFINITIONS ${STAGE_COMPILE_DEFINITIONS} STAGE_LOGGING_OFF) endif() -if (STAGE_API_USAGE_OPENGL) -set (STAGE_COMPILE_DEFINITIONS ${STAGE_COMPILE_DEFINITIONS} STAGE_API_USAGE_OPENGL) -endif() -if (STAGE_API_USAGE_METAL) -set (STAGE_COMPILE_DEFINITIONS ${STAGE_COMPILE_DEFINITIONS} STAGE_API_USAGE_METAL) -endif() - target_compile_definitions(stage PUBLIC ${STAGE_COMPILE_DEFINITIONS}) install(TARGETS stage EXPORT stageConfig @@ -60,7 +53,6 @@ install(FILES DESTINATION include/stage) install(FILES - backstage/alignment.h backstage/camera.h backstage/image.h backstage/light.h diff --git a/src/backstage/alignment.h b/src/backstage/alignment.h deleted file mode 100644 index 3243c76..0000000 --- a/src/backstage/alignment.h +++ /dev/null @@ -1,7 +0,0 @@ -#if defined(STAGE_API_USAGE_OPENGL) -#define DEVICE_ALIGNED alignas(16) -#elif defined(STAGE_API_USAGE_METAL) -#define DEVICE_ALIGNED -#else -#define DEVICE_ALIGNED -#endif \ No newline at end of file diff --git a/src/backstage/buffer.h b/src/backstage/buffer.h index 88ef1ba..4a0e2cc 100644 --- a/src/backstage/buffer.h +++ b/src/backstage/buffer.h @@ -40,7 +40,7 @@ template struct BufferView { BufferView() = default; - BufferView(std::shared_ptr source, size_t offset, size_t num_elements, size_t stride = sizeof(T)) : m_offset(offset), m_size(num_elements), m_stride(stride) { + BufferView(std::shared_ptr source, size_t offset, size_t num_elements, size_t stride = sizeof(T), size_t alignment = alignof(T)) : m_offset(offset), m_size(num_elements), m_stride(stride), m_alignment(alignment) { m_buffer = source; } @@ -48,13 +48,15 @@ struct BufferView { m_offset = source->size(); m_size = 0; m_stride = sizeof(T); + m_alignment = alignof(T); m_buffer = source; } - void setBuffer(std::shared_ptr source, size_t offset, size_t num_elements, size_t stride = sizeof(T)) { + void setBuffer(std::shared_ptr source, size_t offset, size_t num_elements, size_t stride = sizeof(T), size_t alignment = alignof(T)) { m_offset = source->size() + offset; m_size = num_elements; m_stride = stride; + m_alignment = alignment; m_buffer = source; } @@ -90,7 +92,7 @@ struct BufferView { m_size += elements.size(); } - size_t sizeInBytes() const { return m_size * sizeof(T); } + size_t sizeInBytes() const { return m_size * (sizeof(T) + (sizeof(T) % m_alignment)); } size_t size() const { return m_size; } size_t offset() const { return m_offset; } size_t stride() const { return m_stride; } @@ -103,6 +105,7 @@ struct BufferView { std::shared_ptr m_buffer; size_t m_offset; size_t m_stride; + size_t m_alignment; size_t m_size { 0 }; size_t positionInBuffer() { diff --git a/src/backstage/camera.h b/src/backstage/camera.h index 7018337..b85536d 100644 --- a/src/backstage/camera.h +++ b/src/backstage/camera.h @@ -1,15 +1,14 @@ #pragma once -#include "alignment.h" #include "math.h" namespace stage { namespace backstage { -struct DEVICE_ALIGNED Camera { - DEVICE_ALIGNED stage_vec3f position; - DEVICE_ALIGNED stage_vec3f lookat; - DEVICE_ALIGNED stage_vec3f up; +struct Camera { + stage_vec3f position; + stage_vec3f lookat; + stage_vec3f up; float fovy; }; diff --git a/src/backstage/config.h b/src/backstage/config.h index f3893d6..b21cd44 100644 --- a/src/backstage/config.h +++ b/src/backstage/config.h @@ -9,7 +9,8 @@ namespace stage { namespace backstage { struct Config { - VertexLayout layout { VertexLayout_Interleaved_VNT }; + VertexLayout layout { VertexLayout_Interleaved_VNT }; + size_t vertex_alignment { 16 }; }; } diff --git a/src/backstage/light.h b/src/backstage/light.h index ded7658..50efc82 100644 --- a/src/backstage/light.h +++ b/src/backstage/light.h @@ -1,7 +1,6 @@ #pragma once #include -#include "alignment.h" #include "math.h" namespace stage { @@ -15,10 +14,10 @@ namespace backstage { #define SPHERE_LIGHT 3 #define DISK_LIGHT 4 -struct DEVICE_ALIGNED Light { - DEVICE_ALIGNED stage_vec3f L; - DEVICE_ALIGNED stage_vec3f from; - DEVICE_ALIGNED stage_vec3f to; +struct Light { + stage_vec3f L; + stage_vec3f from; + stage_vec3f to; float radius; int32_t map_texid; uint32_t type; diff --git a/src/backstage/material.h b/src/backstage/material.h index 3ec9d4d..8d64185 100644 --- a/src/backstage/material.h +++ b/src/backstage/material.h @@ -1,22 +1,21 @@ #pragma once -#include "alignment.h" #include "math.h" namespace stage { namespace backstage { -struct DEVICE_ALIGNED OpenPBRMaterial { +struct OpenPBRMaterial { /* Base */ - DEVICE_ALIGNED stage_vec3f base_color; + stage_vec3f base_color; int32_t base_color_texid; float base_weight; float base_roughness; float base_metalness; /* Specular */ - DEVICE_ALIGNED stage_vec3f specular_color; + stage_vec3f specular_color; float specular_weight; float specular_roughness; float specular_anisotropy; diff --git a/src/backstage/math.h b/src/backstage/math.h index 54e4e73..372b30a 100644 --- a/src/backstage/math.h +++ b/src/backstage/math.h @@ -203,5 +203,10 @@ compMin(const stage_vec3& v) { return min < v.z ? min : v.z; } +template size_t +sizeofAligned(size_t alignment) { + return sizeof(T) + (sizeof(T) % alignment); +} + } } diff --git a/src/backstage/mesh.cpp b/src/backstage/mesh.cpp index 6545ee7..5215fac 100644 --- a/src/backstage/mesh.cpp +++ b/src/backstage/mesh.cpp @@ -1,5 +1,4 @@ #include "mesh.h" -#include "log.h" namespace stage { namespace backstage { @@ -17,57 +16,57 @@ Geometry::Geometry(Object& parent, std::vector positions, std::vect switch (layout) { case VertexLayout_Block_V: - stride_positions = sizeof(stage_vec3f); + stride_positions = sizeofAligned(parent.alignment()); offset_positions = 0; - stride_material_ids = sizeof(uint32_t); + stride_material_ids = sizeofAligned(parent.alignment()); offset_material_ids = positions.size() * stride_positions; break; case VertexLayout_Block_VN: - stride_positions = sizeof(stage_vec3f); + stride_positions = sizeofAligned(parent.alignment()); offset_positions = 0; - stride_normals = sizeof(stage_vec3f); + stride_normals = sizeofAligned(parent.alignment()); offset_normals = positions.size() * stride_positions; - stride_material_ids = sizeof(uint32_t); + stride_material_ids = sizeofAligned(parent.alignment()); offset_material_ids = offset_normals + normals.size() * stride_normals; break; case VertexLayout_Block_VNT: - stride_positions = sizeof(stage_vec3f); + stride_positions = sizeofAligned(parent.alignment()); offset_positions = 0; - stride_normals = sizeof(stage_vec3f); + stride_normals = sizeofAligned(parent.alignment()); offset_normals = positions.size() * stride_positions; - stride_uvs = sizeof(stage_vec2f); + stride_uvs = sizeofAligned(parent.alignment()); offset_uvs = offset_normals + normals.size() * stride_normals; - stride_material_ids = sizeof(uint32_t); + stride_material_ids = sizeofAligned(parent.alignment()); offset_material_ids = offset_uvs + uvs.size() * stride_uvs; break; case VertexLayout_Interleaved_V: offset_positions = 0; - offset_material_ids = sizeof(stage_vec3f); - stride_positions = stride_material_ids = sizeof(stage_vec3f) + sizeof(uint32_t); + offset_material_ids = sizeofAligned(parent.alignment()); + stride_positions = stride_material_ids = sizeofAligned(parent.alignment()) + sizeofAligned(parent.alignment()); break; case VertexLayout_Interleaved_VN: offset_positions = 0; - offset_normals = sizeof(stage_vec3f); - offset_material_ids = offset_normals + sizeof(stage_vec3f); - stride_positions = stride_normals = stride_material_ids = 2 * sizeof(stage_vec3f) + sizeof(uint32_t); + offset_normals = sizeofAligned(parent.alignment()); + offset_material_ids = offset_normals + sizeofAligned(parent.alignment()); + stride_positions = stride_normals = stride_material_ids = 2 * sizeofAligned(parent.alignment()) + sizeofAligned(parent.alignment()); break; case VertexLayout_Interleaved_VNT: offset_positions = 0; - offset_normals = sizeof(stage_vec3f); - offset_uvs = offset_normals + sizeof(stage_vec3f); - offset_material_ids = offset_uvs + sizeof(stage_vec2f); - stride_positions = stride_normals = stride_uvs = stride_material_ids = 2 * sizeof(stage_vec3f) + sizeof(stage_vec2f) + sizeof(uint32_t); + offset_normals = sizeofAligned(parent.alignment()); + offset_uvs = offset_normals + sizeofAligned(parent.alignment()); + offset_material_ids = offset_uvs + sizeofAligned(parent.alignment()); + stride_positions = stride_normals = stride_uvs = stride_material_ids = 2 * sizeofAligned(parent.alignment()) + sizeofAligned(parent.alignment()) + sizeofAligned(parent.alignment()); break; default: break; } - this->positions.setBuffer(parent.data, offset_positions, 0, stride_positions); + this->positions.setBuffer(parent.data, offset_positions, 0, stride_positions, parent.alignment()); if (layout & (VertexLayout_Block_VN | VertexLayout_Interleaved_VN | VertexLayout_Block_VNT | VertexLayout_Interleaved_VNT)) - this->normals.setBuffer(parent.data, offset_normals, 0, stride_normals); + this->normals.setBuffer(parent.data, offset_normals, 0, stride_normals, parent.alignment()); if (layout & (VertexLayout_Block_VNT | VertexLayout_Interleaved_VNT)) - this->uvs.setBuffer(parent.data, offset_uvs, 0, stride_uvs); - this->material_ids.setBuffer(parent.data, offset_material_ids, 0, stride_material_ids); + this->uvs.setBuffer(parent.data, offset_uvs, 0, stride_uvs, parent.alignment()); + this->material_ids.setBuffer(parent.data, offset_material_ids, 0, stride_material_ids, parent.alignment()); this->positions.push_back(positions); if (layout & (VertexLayout_Block_VN | VertexLayout_Interleaved_VN | VertexLayout_Block_VNT | VertexLayout_Interleaved_VNT)) @@ -77,6 +76,6 @@ Geometry::Geometry(Object& parent, std::vector positions, std::vect this->material_ids.push_back(material_ids); } -Object::Object(VertexLayout layout) : m_layout(layout), data(std::make_shared()) {} +Object::Object(VertexLayout layout, size_t alignment) : m_layout(layout), m_alignment(alignment), data(std::make_shared()) {} } } \ No newline at end of file diff --git a/src/backstage/mesh.h b/src/backstage/mesh.h index 87d72e0..5fa0661 100644 --- a/src/backstage/mesh.h +++ b/src/backstage/mesh.h @@ -3,7 +3,6 @@ #include #include #include "math.h" -#include "alignment.h" #include "buffer.h" namespace stage { @@ -18,13 +17,6 @@ enum VertexLayout { VertexLayout_Block_V = 0x020, }; -struct DEVICE_ALIGNED AlignedVertex { - DEVICE_ALIGNED stage_vec3f position; - DEVICE_ALIGNED stage_vec3f normal; - DEVICE_ALIGNED stage_vec2f uv; - uint32_t material_id; -}; - struct Object; struct Geometry { Geometry(Object& parent, std::vector positions, std::vector normals, std::vector uvs, std::vector material_ids, std::vector indices); @@ -37,13 +29,15 @@ struct Geometry { }; struct Object { - Object(VertexLayout layout); + Object(VertexLayout layout, size_t alignment); std::shared_ptr data; std::vector geometries; VertexLayout layout() { return m_layout; } + size_t alignment() { return m_alignment; } private: VertexLayout m_layout; + size_t m_alignment; }; struct ObjectInstance { diff --git a/src/backstage/scene.cpp b/src/backstage/scene.cpp index fcbf43e..b08e136 100644 --- a/src/backstage/scene.cpp +++ b/src/backstage/scene.cpp @@ -198,7 +198,7 @@ OBJScene::loadObj() { m_materials.push_back(OpenPBRMaterial::defaultMaterial()); // Parse meshes - Object obj(m_config.layout); + Object obj(m_config.layout, m_config.vertex_alignment); for (const auto& shape : shapes) { const auto& mesh = shape.mesh; @@ -235,20 +235,12 @@ OBJScene::loadObj() { } else { g_index = g_n_unique_idx_cnt++; - AlignedVertex vertex; - vertex.position = make_vec3(&attrib.vertices[3 * idx.vertex_index]); - vertex.normal = make_vec3(&attrib.normals[3 * idx.normal_index]); + positions.push_back(make_vec3(&attrib.vertices[3 * idx.vertex_index])); + normals.push_back(make_vec3(&attrib.normals[3 * idx.normal_index])); if (attrib.texcoords.size() > 0) { - vertex.uv = make_vec2(&attrib.texcoords[2 * idx.texcoord_index]); + uvs.push_back(make_vec2(&attrib.texcoords[2 * idx.texcoord_index])); } - vertex.material_id = mesh.material_ids[f] < 0 ? m_materials.size() - 1 : mesh.material_ids[f]; - - positions.push_back(vertex.position); - normals.push_back(vertex.normal); - if (attrib.texcoords.size() > 0) { - uvs.push_back(vertex.uv); - } - material_ids.push_back(vertex.material_id); + material_ids.push_back(mesh.material_ids[f] < 0 ? m_materials.size() - 1 : mesh.material_ids[f]); index_map[key] = g_index; } @@ -479,7 +471,7 @@ PBRTScene::loadPBRTObjectsRecursive(std::shared_ptr current, if (!current || object_map.find(current) != object_map.end()) return; // Load shapes - Object obj(m_config.layout); + Object obj(m_config.layout, m_config.vertex_alignment); for (auto& shape : current->shapes) { // Non-triangle shapes are not supported pbrt::TriangleMesh::SP mesh = std::dynamic_pointer_cast(shape); @@ -505,30 +497,24 @@ PBRTScene::loadPBRTObjectsRecursive(std::shared_ptr current, for (auto& index : mesh->index) { for (int i = 0; i < 3; i++) { - AlignedVertex vertex; auto position = mesh->vertex[*(&index.x + i)]; - vertex.position = make_vec3(&position.x); + positions.push_back(make_vec3(&position.x)); if (mesh->normal.size() > 0) { auto normal = mesh->normal[*(&index.x + i)]; - vertex.normal = make_vec3(&normal.x); + normals.push_back(make_vec3(&normal.x)); } else { const auto& v0 = make_vec3(&mesh->vertex[index.x].x); const auto& v1 = make_vec3(&mesh->vertex[index.y].x); const auto& v2 = make_vec3(&mesh->vertex[index.z].x); - vertex.normal = normalize(cross((v1 - v0), (v2 - v0))); + normals.push_back(normalize(cross((v1 - v0), (v2 - v0)))); } if (mesh->texcoord.size() > 0) { auto uv = mesh->texcoord[*(&index.x + i)]; - vertex.uv = make_vec2(&uv.x); + uvs.push_back(make_vec2(&uv.x)); } - - vertex.material_id = material_id; - positions.push_back(vertex.position); - normals.push_back(vertex.normal); - uvs.push_back(vertex.uv); - material_ids.push_back(vertex.material_id); + material_ids.push_back(material_id); indices.emplace_back(g_n_idx_cnt++); } } @@ -1033,7 +1019,7 @@ void FBXScene::loadFBX() { auto* fbx_mesh = fbx_scene->meshes[meshid]; if (fbx_mesh->instances.count == 0) continue; - Object obj(m_config.layout); + Object obj(m_config.layout, m_config.vertex_alignment); std::map index_map; @@ -1061,32 +1047,33 @@ void FBXScene::loadFBX() { ufbx_vec3 position = ufbx_get_vertex_vec3(&fbx_mesh->vertex_position, index); ufbx_vec3 normal = ufbx_get_vertex_vec3(&fbx_mesh->vertex_normal, index); ufbx_vec2 uv = fbx_mesh->vertex_uv.exists ? ufbx_get_vertex_vec2(&fbx_mesh->vertex_uv, index) : ufbx_vec2({0, 0}); - AlignedVertex vertex; - vertex.position.x = position.x; - vertex.position.y = position.y; - vertex.position.z = position.z; - vertex.normal.x = normal.x; - vertex.normal.y = normal.y; - vertex.normal.z = normal.z; - vertex.uv.x = uv.x; - vertex.uv.y = uv.y; + stage_vec3f stage_position; + stage_position.x = position.x; + stage_position.y = position.y; + stage_position.z = position.z; + stage_vec3f stage_normal; + stage_normal.x = normal.x; + stage_normal.y = normal.y; + stage_normal.z = normal.z; + stage_vec2f stage_uv; + stage_uv.x = uv.x; + stage_uv.y = uv.y; + positions.push_back(stage_position); + normals.push_back(stage_normal); + uvs.push_back(stage_uv); if (fbx_mesh->face_material.count > 0) { auto* fbx_material = fbx_mesh->materials.data[fbx_mesh->face_material[faceid]]; uint32_t materialid = fbx_material->element_id; if (material_map.find(materialid) != material_map.end()) { - vertex.material_id = material_map.at(materialid); + material_ids.push_back(material_map.at(materialid)); } else { - vertex.material_id = m_materials.size() - 1; + material_ids.push_back(m_materials.size() - 1); } } else { - vertex.material_id = m_materials.size() - 1; + material_ids.push_back(m_materials.size() - 1); } - positions.push_back(vertex.position); - normals.push_back(vertex.normal); - uvs.push_back(vertex.uv); - material_ids.push_back(vertex.material_id); index_map[index] = g_index; } indices.push_back(g_index); From 88550f1aeb6f306c453364a036a05893d77dd132 Mon Sep 17 00:00:00 2001 From: David Bauer Date: Thu, 25 Apr 2024 20:21:56 -0700 Subject: [PATCH 2/2] Update tests for alignment --- tests/test_mesh.cpp | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/tests/test_mesh.cpp b/tests/test_mesh.cpp index f40a556..fad7749 100644 --- a/tests/test_mesh.cpp +++ b/tests/test_mesh.cpp @@ -1,12 +1,12 @@ #include "test_common.h" TEST(Object, CreateEmpty) { - Object obj(VertexLayout_Block_VNT); + Object obj(VertexLayout_Block_VNT, 4); EXPECT_EQ(obj.data->size(), 0); } TEST(Object, CreateWithEmptyGeometry) { - Object obj(VertexLayout_Block_VNT); + Object obj(VertexLayout_Block_VNT, 4); Geometry g = make_geometry(obj, 0, 0); obj.geometries.push_back(g); @@ -15,7 +15,7 @@ TEST(Object, CreateWithEmptyGeometry) { } TEST(Object, CreateWithPopulatedGeometry) { - Object obj(VertexLayout_Block_VNT); + Object obj(VertexLayout_Block_VNT, 4); Geometry g = make_geometry(obj, 512, 512); obj.geometries.push_back(g); @@ -25,8 +25,8 @@ TEST(Object, CreateWithPopulatedGeometry) { } void -test_layout(VertexLayout layout) { - Object obj(layout); +test_layout(VertexLayout layout, size_t alignment) { + Object obj(layout, alignment); Geometry g0 = make_geometry(obj, 512, 512); Geometry g1 = make_geometry(obj, 512, 512); @@ -54,25 +54,31 @@ test_layout(VertexLayout layout) { } TEST(Object, LayoutInterleavedV) { - test_layout(VertexLayout_Interleaved_V); + for (auto alignment : {4, 8, 16, 32, 128}) + test_layout(VertexLayout_Interleaved_V, alignment); } TEST(Object, LayoutInterleavedVN) { - test_layout(VertexLayout_Interleaved_VN); + for (auto alignment : {4, 8, 16, 32, 128}) + test_layout(VertexLayout_Interleaved_VN, alignment); } TEST(Object, LayoutInterleavedVNT) { - test_layout(VertexLayout_Interleaved_VNT); + for (auto alignment : {4, 8, 16, 32, 128}) + test_layout(VertexLayout_Interleaved_VNT, alignment); } TEST(Object, LayoutBlockV) { - test_layout(VertexLayout_Block_V); + for (auto alignment : {4, 8, 16, 32, 128}) + test_layout(VertexLayout_Block_V, alignment); } TEST(Object, LayoutBlockVN) { - test_layout(VertexLayout_Block_VN); + for (auto alignment : {4, 8, 16, 32, 128}) + test_layout(VertexLayout_Block_VN, alignment); } TEST(Object, LayoutBlockVNT) { - test_layout(VertexLayout_Block_VNT); + for (auto alignment : {4, 8, 16, 32, 128}) + test_layout(VertexLayout_Block_VNT, alignment); } \ No newline at end of file