From 93f11a006b94ccecd7a1fd1dfba0adff56ae7c38 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Wed, 19 Apr 2023 00:51:35 +0100 Subject: Drop performance debug to warning and stop disabling error checking for texture save --- test/test-assetFactory.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'test/test-assetFactory.cpp') diff --git a/test/test-assetFactory.cpp b/test/test-assetFactory.cpp index 3d79213..82543f3 100644 --- a/test/test-assetFactory.cpp +++ b/test/test-assetFactory.cpp @@ -29,7 +29,6 @@ public: FactoryFixture() : sceneRenderer {size, output} { } ~FactoryFixture() { - glDisable(GL_DEBUG_OUTPUT); auto outpath = (TMP / boost::unit_test::framework::current_test_case().full_name()).replace_extension(".tga"); std::filesystem::create_directories(outpath.parent_path()); Texture::save(outImage, outpath.c_str()); -- cgit v1.2.3 From ac05fbbc71282b059164b51efd68ee6e372870cb Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Thu, 20 Apr 2023 20:27:43 +0100 Subject: Switch to render trees in bulk through foliage asset rendering --- game/scenary/foliage.cpp | 22 ++++++++++++++-------- game/scenary/foliage.h | 10 +++++++--- game/scenary/plant.cpp | 12 +++--------- game/scenary/plant.h | 12 +++++------- test/test-assetFactory.cpp | 2 +- ui/gameMainWindow.cpp | 10 ++++++++++ 6 files changed, 40 insertions(+), 28 deletions(-) (limited to 'test/test-assetFactory.cpp') diff --git a/game/scenary/foliage.cpp b/game/scenary/foliage.cpp index d39d500..35be051 100644 --- a/game/scenary/foliage.cpp +++ b/game/scenary/foliage.cpp @@ -1,7 +1,9 @@ #include "foliage.h" #include "gfx/gl/sceneShader.h" #include "gfx/gl/shadowMapper.h" +#include "gfx/gl/vertexArrayObject.hpp" #include "gfx/models/texture.h" +#include "location.hpp" bool Foliage::persist(Persistence::PersistenceStore & store) @@ -13,21 +15,25 @@ void Foliage::postLoad() { texture = getTexture(); + bodyMesh->configureVAO(instanceVAO).addAttribs(instances.bufferName(), 1); } void -Foliage::render(const SceneShader & shader, const Location & loc) const +Foliage::render(const SceneShader & shader) const { - shader.basic.use(loc); - if (texture) { - texture->bind(); + if (const auto count = instances.count()) { + shader.basicInst.use(); + if (texture) { + texture->bind(); + } + glBindVertexArray(instanceVAO); + glDrawElementsInstanced( + bodyMesh->type(), bodyMesh->count(), GL_UNSIGNED_INT, nullptr, static_cast(count)); + glBindVertexArray(0); } - bodyMesh->Draw(); } void -Foliage::shadows(const ShadowMapper & mapper, const Location & loc) const +Foliage::shadows(const ShadowMapper &) const { - mapper.dynamicPoint.use(loc); - bodyMesh->Draw(); } diff --git a/game/scenary/foliage.h b/game/scenary/foliage.h index b85aab2..b72a9c2 100644 --- a/game/scenary/foliage.h +++ b/game/scenary/foliage.h @@ -1,19 +1,23 @@ #pragma once #include "assetFactory/asset.h" +#include "gfx/gl/instanceVertices.h" +#include "gfx/renderable.h" class SceneShader; class ShadowMapper; class Location; class Texture; -class Foliage : public Asset, public StdTypeDefs { +class Foliage : public Asset, public Renderable, public StdTypeDefs { Mesh::Ptr bodyMesh; std::shared_ptr texture; + glVertexArray instanceVAO; public: - void render(const SceneShader &, const Location &) const; - void shadows(const ShadowMapper &, const Location &) const; + mutable InstanceVertices instances; + void render(const SceneShader &) const override; + void shadows(const ShadowMapper &) const override; protected: friend Persistence::SelectionPtrBase>; diff --git a/game/scenary/plant.cpp b/game/scenary/plant.cpp index 2b01bee..678d4a7 100644 --- a/game/scenary/plant.cpp +++ b/game/scenary/plant.cpp @@ -1,13 +1,7 @@ #include "plant.h" -void -Plant::render(const SceneShader & shader) const +Plant::Plant(std::shared_ptr type, Location position) : + type {std::move(type)}, + location {this->type->instances.acquire(glm::translate(position.pos) * rotate_ypr(position.rot))} { - type->render(shader, position); -} - -void -Plant::shadows(const ShadowMapper & mapper) const -{ - type->shadows(mapper, position); } diff --git a/game/scenary/plant.h b/game/scenary/plant.h index 55acca1..77c5979 100644 --- a/game/scenary/plant.h +++ b/game/scenary/plant.h @@ -2,15 +2,13 @@ #include "foliage.h" #include "game/worldobject.h" -#include "gfx/renderable.h" #include "location.hpp" +#include "maths.h" +#include -class Plant : public Renderable, public WorldObject { +class Plant : public WorldObject { std::shared_ptr type; - Location position; - - void render(const SceneShader & shader) const override; - void shadows(const ShadowMapper & shadowMapper) const override; + InstanceVertices::InstanceProxy location; void tick(TickDuration) override @@ -18,5 +16,5 @@ class Plant : public Renderable, public WorldObject { } public: - Plant(std::shared_ptr type, Location position) : type(std::move(type)), position(position) { } + Plant(std::shared_ptr type, Location position); }; diff --git a/test/test-assetFactory.cpp b/test/test-assetFactory.cpp index 82543f3..817654b 100644 --- a/test/test-assetFactory.cpp +++ b/test/test-assetFactory.cpp @@ -108,7 +108,7 @@ BOOST_AUTO_TEST_CASE(foliage, *boost::unit_test::timeout(5)) BOOST_REQUIRE(tree_01_1_f); auto plant = std::make_shared(tree_01_1_f, Location {{-2, 2, 0}, {}}); - objects.objects.push_back(plant); + objects.objects.push_back(tree_01_1_f); render(5); } diff --git a/ui/gameMainWindow.cpp b/ui/gameMainWindow.cpp index 0b30cad..3f85a4f 100644 --- a/ui/gameMainWindow.cpp +++ b/ui/gameMainWindow.cpp @@ -51,6 +51,11 @@ GameMainWindow::render() const void GameMainWindow::content(const SceneShader & shader) const { + for (const auto & [id, asset] : gameState->assets) { + if (const auto r = std::dynamic_pointer_cast(asset)) { + r->render(shader); + } + } gameState->world.apply(&Renderable::render, shader); uiComponents.apply(&WorldOverlay::render, shader); } @@ -68,5 +73,10 @@ GameMainWindow::lights(const SceneShader & shader) const void GameMainWindow::shadows(const ShadowMapper & shadowMapper) const { + for (const auto & [id, asset] : gameState->assets) { + if (const auto r = std::dynamic_pointer_cast(asset)) { + r->shadows(shadowMapper); + } + } gameState->world.apply(&Renderable::shadows, shadowMapper); } -- cgit v1.2.3 From ab5b46dbe58ae0401c24ead55a2627b9a577fc1a Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 21 Apr 2023 23:52:56 +0100 Subject: Instances buffer data needs to be unmapped before use Here we change quite a bit to support mapping and unmapping the buffer as required. The instance/free referencing is still broken though. We add several instances of tree in the render. --- gfx/gl/instanceVertices.h | 66 ++++++++++++++++++++++++++++++++-------------- test/Jamfile.jam | 2 +- test/test-assetFactory.cpp | 5 +++- test/test-instancing.cpp | 15 +++++++---- 4 files changed, 61 insertions(+), 27 deletions(-) (limited to 'test/test-assetFactory.cpp') diff --git a/gfx/gl/instanceVertices.h b/gfx/gl/instanceVertices.h index dc28a4d..c2ddb1d 100644 --- a/gfx/gl/instanceVertices.h +++ b/gfx/gl/instanceVertices.h @@ -9,11 +9,9 @@ template class InstanceVertices { public: - InstanceVertices(size_t initialSize = 16) : data {allocBuffer(buffer, initialSize)}, next {} { } - - ~InstanceVertices() + InstanceVertices(size_t initialSize = 16) { - glUnmapNamedBuffer(buffer); + allocBuffer(initialSize); } class InstanceProxy { @@ -50,17 +48,20 @@ public: T & operator=(U && v) { + instances->map(); return instances->data[index] = std::forward(v); } T * get() { + instances->map(); return &instances->data[index]; } const T * get() const { + instances->map(); return &instances->data[index]; } T * @@ -95,22 +96,24 @@ public: InstanceProxy acquire(Params &&... params) { + map(); if (!unused.empty()) { auto idx = unused.back(); unused.pop_back(); - new (&data[idx]) T(std::forward(params)...); + new (data + idx) T(std::forward(params)...); return InstanceProxy {this, idx}; } - if (next >= data.size()) { - resize(data.size() * 2); + if (next >= capacity) { + resize(capacity * 2); } - new (&data[next]) T(std::forward(params)...); + new (data + next) T(std::forward(params)...); return InstanceProxy {this, next++}; } void release(const InstanceProxy & p) { + map(); data[p.index].~T(); unused.push_back(p.index); } @@ -118,42 +121,65 @@ public: const auto & bufferName() const { + unmap(); return buffer; } auto count() const { + unmap(); return next; } protected: friend InstanceProxy; - static std::span - allocBuffer(const glBuffer & buffer, std::size_t count) + void + allocBuffer(std::size_t newCapacity) { glBindBuffer(GL_ARRAY_BUFFER, buffer); - glBufferData(GL_ARRAY_BUFFER, static_cast(sizeof(T) * count), nullptr, GL_DYNAMIC_DRAW); - auto data = static_cast(glMapNamedBuffer(buffer, GL_READ_WRITE)); + glBufferData(GL_ARRAY_BUFFER, static_cast(sizeof(T) * newCapacity), nullptr, GL_DYNAMIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); - return {data, count}; + capacity = newCapacity; + data = nullptr; } void resize(size_t newCapacity) { - const auto maintain = std::min(newCapacity, data.size()); - const auto maintaind = static_cast(maintain); + const auto maintain = std::min(newCapacity, capacity); std::vector existing; + const auto maintaind = static_cast(maintain); existing.reserve(maintain); - std::move(data.begin(), data.begin() + maintaind, std::back_inserter(existing)); - data = allocBuffer(buffer, newCapacity); - std::move(existing.begin(), existing.begin() + maintaind, data.begin()); + map(); + std::move(data, data + maintain, std::back_inserter(existing)); + allocBuffer(newCapacity); + map(); + std::move(existing.begin(), existing.begin() + maintaind, data); + capacity = newCapacity; + } + + void + map() const + { + if (!data) { + data = static_cast(glMapNamedBuffer(buffer, GL_READ_WRITE)); + } + } + + void + unmap() const + { + if (data) { + glUnmapNamedBuffer(buffer); + data = nullptr; + } } glBuffer buffer; - std::span data; - std::size_t next; + mutable T * data {}; + std::size_t capacity {}; + std::size_t next {}; std::vector unused; }; diff --git a/test/Jamfile.jam b/test/Jamfile.jam index 9cdcef4..1ce73b7 100644 --- a/test/Jamfile.jam +++ b/test/Jamfile.jam @@ -53,7 +53,7 @@ run test-text.cpp ; run test-enumDetails.cpp ; run test-render.cpp : -- : test-assetFactory : test ; run test-glContextBhvr.cpp ; -run test-assetFactory.cpp : -- : [ sequence.insertion-sort [ glob-tree $(res) : *.* ] fixtures/rgb.txt ] : test ; +run test-assetFactory.cpp : -- : [ sequence.insertion-sort [ glob-tree $(res) : *.* ] fixtures/rgb.txt test-instancing ] : test ; run perf-assetFactory.cpp : -- : test-assetFactory : benchmark test ; run perf-persistence.cpp : -- : test-persistence : benchmark test ; run test-worker.cpp ; diff --git a/test/test-assetFactory.cpp b/test/test-assetFactory.cpp index 817654b..82a1825 100644 --- a/test/test-assetFactory.cpp +++ b/test/test-assetFactory.cpp @@ -107,7 +107,10 @@ BOOST_AUTO_TEST_CASE(foliage, *boost::unit_test::timeout(5)) auto tree_01_1_f = std::dynamic_pointer_cast(tree_01_1); BOOST_REQUIRE(tree_01_1_f); - auto plant = std::make_shared(tree_01_1_f, Location {{-2, 2, 0}, {}}); + auto plant1 = std::make_shared(tree_01_1_f, Location {{-2, 2, 0}, {0, 0, 0}}); + auto plant2 = std::make_shared(tree_01_1_f, Location {{3, -4, 0}, {0, 1, 0}}); + auto plant3 = std::make_shared(tree_01_1_f, Location {{-2, -4, 0}, {0, 2, 0}}); + auto plant4 = std::make_shared(tree_01_1_f, Location {{3, 2, 0}, {0, 3, 0}}); objects.objects.push_back(tree_01_1_f); render(5); diff --git a/test/test-instancing.cpp b/test/test-instancing.cpp index 7191567..2eb3647 100644 --- a/test/test-instancing.cpp +++ b/test/test-instancing.cpp @@ -15,16 +15,21 @@ BOOST_FIXTURE_TEST_SUITE(i, InstanceVertices) BOOST_AUTO_TEST_CASE(createDestroy) { - BOOST_REQUIRE(data.data()); + BOOST_CHECK(!data); + map(); + BOOST_REQUIRE(data); BOOST_CHECK_EQUAL(0, next); BOOST_CHECK(unused.empty()); + unmap(); + BOOST_CHECK(!data); } BOOST_AUTO_TEST_CASE(storeRetreive) { // Read write raw buffer, not normally allowed - std::vector test(data.size()); - std::copy(test.begin(), test.end(), data.begin()); - BOOST_CHECK_EQUAL_COLLECTIONS(test.begin(), test.end(), data.begin(), data.end()); + std::vector test(capacity); + map(); + std::copy(test.begin(), test.end(), data); + BOOST_CHECK_EQUAL_COLLECTIONS(test.begin(), test.end(), data, data + capacity); } BOOST_AUTO_TEST_CASE(acquireRelease) @@ -69,7 +74,7 @@ BOOST_AUTO_TEST_CASE(resize) proxies.push_back(acquire(n)); expected.emplace_back(n); } - BOOST_CHECK_EQUAL_COLLECTIONS(expected.begin(), expected.end(), data.begin(), data.begin() + COUNT); + BOOST_CHECK_EQUAL_COLLECTIONS(expected.begin(), expected.end(), data, data + COUNT); BOOST_CHECK_EQUAL_COLLECTIONS(expected.begin(), expected.end(), proxies.begin(), proxies.end()); } -- cgit v1.2.3