Optimize surface providers (#7631)

* Add comparison operators to SurfaceTagWeight.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Changed AddSurfaceTagWeight to always combine weights.
This simplifies the API a bit and defines the behavior if someone ever tries to add a duplicate tag.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Added benchmarks for measuring the performance-critical APIs.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Changed SurfaceTagWeights to a fixed_vector.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Add inPosition to AddSurfacePoint.
This will be used to detect which input the surface point is associated with.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Add inPositionIndex to the appropriate APIs.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Switched Gradient Surface benchmarks to use actual surface components.
The gradient unit tests and benchmarks were previously using a mock surface data system, which led to misleading benchmark results. Now, the actual SurfaceData system gets constructed, and the tests use a mock provider, but the benchmarks use actual shape providers for more realistic benchmarking.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Fixed unit tests to have better query ranges.
Half of each previous range was querying outside the surface provider's data.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* First attempt at removing SurfacePointLists.
This currently runs significantly slower than the previous code but passes the unit tests.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Another attempt at optimization.
This one runs faster than the previous, but still slow.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Fix the cmake dependency so that the gradient tests rebuild SurfaceData.dll when run.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Switch SurfaceAltitudeGradient over to the new bulk API.
Also, optimized the non-bulk API by having it reuse the SurfacePointList to avoid the repeated allocation / deallocation cost.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Switched to using an indirect index so that all allocations are consecutive in our reserved buffer.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Switched back to SurfaceTagWeight again.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Added runtime dependency to LmbrCentral for unit tests.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Switched code over to use the full EnumeratePoints in most cases.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Added knowledge of max surface point creation into the system.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Add generic GetSurfacePointsFromList API implementation for surface providers.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Fixed implementation to use the correct maximum number of input points based on the surface providers being queried.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Fix out-of-bounds references on empty lists.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Fix memory allocation that caused benchmark runs to crash.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Starting to clean up the API.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Move SurfacePointList into separate files for easier maintainability.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Fixed bug where too many points were filtered out due to using the position Z as a part of the AABB check.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Made FilterPoints an internal part of SurfacePointList so we can choose when and how to perform the filtering.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Final cleanup / comments.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Added includes for non-unity builds.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Optimized GetValues() implementations.
Also consolidated GetValue() and GetValues() down to a single implementation under the covers for easier maintenance.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Changed how unit tests initialize the mock lists to try and fix the linux errors.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Switch to explicit span declarations to help ensure this works with linux.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Fixed compile error.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Make the bulk terrain APIs take in const Vector instead of non-const.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Optimize the surface data providers for bulk queries.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>
This commit is contained in:
Mike Balfour
2022-02-16 09:17:01 -06:00
committed by GitHub
parent 1413977aca
commit 0e328afcdd
18 changed files with 286 additions and 296 deletions
@@ -140,28 +140,28 @@ namespace AzFramework
//! Given a list of XY coordinates, call the provided callback function with surface data corresponding to each
//! XY coordinate in the list.
virtual void ProcessHeightsFromList(const AZStd::span<AZ::Vector3>& inPositions,
virtual void ProcessHeightsFromList(const AZStd::span<const AZ::Vector3>& inPositions,
SurfacePointListFillCallback perPositionCallback,
Sampler sampleFilter = Sampler::DEFAULT) const = 0;
virtual void ProcessNormalsFromList(const AZStd::span<AZ::Vector3>& inPositions,
virtual void ProcessNormalsFromList(const AZStd::span<const AZ::Vector3>& inPositions,
SurfacePointListFillCallback perPositionCallback,
Sampler sampleFilter = Sampler::DEFAULT) const = 0;
virtual void ProcessSurfaceWeightsFromList(const AZStd::span<AZ::Vector3>& inPositions,
virtual void ProcessSurfaceWeightsFromList(const AZStd::span<const AZ::Vector3>& inPositions,
SurfacePointListFillCallback perPositionCallback,
Sampler sampleFilter = Sampler::DEFAULT) const = 0;
virtual void ProcessSurfacePointsFromList(const AZStd::span<AZ::Vector3>& inPositions,
virtual void ProcessSurfacePointsFromList(const AZStd::span<const AZ::Vector3>& inPositions,
SurfacePointListFillCallback perPositionCallback,
Sampler sampleFilter = Sampler::DEFAULT) const = 0;
virtual void ProcessHeightsFromListOfVector2(const AZStd::span<AZ::Vector2>& inPositions,
virtual void ProcessHeightsFromListOfVector2(const AZStd::span<const AZ::Vector2>& inPositions,
SurfacePointListFillCallback perPositionCallback,
Sampler sampleFilter = Sampler::DEFAULT) const = 0;
virtual void ProcessNormalsFromListOfVector2(const AZStd::span<AZ::Vector2>& inPositions,
virtual void ProcessNormalsFromListOfVector2(const AZStd::span<const AZ::Vector2>& inPositions,
SurfacePointListFillCallback perPositionCallback,
Sampler sampleFilter = Sampler::DEFAULT) const = 0;
virtual void ProcessSurfaceWeightsFromListOfVector2(const AZStd::span<AZ::Vector2>& inPositions,
virtual void ProcessSurfaceWeightsFromListOfVector2(const AZStd::span<const AZ::Vector2>& inPositions,
SurfacePointListFillCallback perPositionCallback,
Sampler sampleFilter = Sampler::DEFAULT) const = 0;
virtual void ProcessSurfacePointsFromListOfVector2(const AZStd::span<AZ::Vector2>& inPositions,
virtual void ProcessSurfacePointsFromListOfVector2(const AZStd::span<const AZ::Vector2>& inPositions,
SurfacePointListFillCallback perPositionCallback,
Sampler sampleFilter = Sampler::DEFAULT) const = 0;
@@ -272,42 +272,42 @@ namespace AzFramework
//! Asynchronous versions of the various 'Process*' API functions declared above.
//! It's the responsibility of the caller to ensure all callbacks are threadsafe.
virtual AZStd::shared_ptr<TerrainJobContext> ProcessHeightsFromListAsync(
const AZStd::span<AZ::Vector3>& inPositions,
const AZStd::span<const AZ::Vector3>& inPositions,
SurfacePointListFillCallback perPositionCallback,
Sampler sampleFilter = Sampler::DEFAULT,
AZStd::shared_ptr<ProcessAsyncParams> params = nullptr) const = 0;
virtual AZStd::shared_ptr<TerrainJobContext> ProcessNormalsFromListAsync(
const AZStd::span<AZ::Vector3>& inPositions,
const AZStd::span<const AZ::Vector3>& inPositions,
SurfacePointListFillCallback perPositionCallback,
Sampler sampleFilter = Sampler::DEFAULT,
AZStd::shared_ptr<ProcessAsyncParams> params = nullptr) const = 0;
virtual AZStd::shared_ptr<TerrainJobContext> ProcessSurfaceWeightsFromListAsync(
const AZStd::span<AZ::Vector3>& inPositions,
const AZStd::span<const AZ::Vector3>& inPositions,
SurfacePointListFillCallback perPositionCallback,
Sampler sampleFilter = Sampler::DEFAULT,
AZStd::shared_ptr<ProcessAsyncParams> params = nullptr) const = 0;
virtual AZStd::shared_ptr<TerrainJobContext> ProcessSurfacePointsFromListAsync(
const AZStd::span<AZ::Vector3>& inPositions,
const AZStd::span<const AZ::Vector3>& inPositions,
SurfacePointListFillCallback perPositionCallback,
Sampler sampleFilter = Sampler::DEFAULT,
AZStd::shared_ptr<ProcessAsyncParams> params = nullptr) const = 0;
virtual AZStd::shared_ptr<TerrainJobContext> ProcessHeightsFromListOfVector2Async(
const AZStd::span<AZ::Vector2>& inPositions,
const AZStd::span<const AZ::Vector2>& inPositions,
SurfacePointListFillCallback perPositionCallback,
Sampler sampleFilter = Sampler::DEFAULT,
AZStd::shared_ptr<ProcessAsyncParams> params = nullptr) const = 0;
virtual AZStd::shared_ptr<TerrainJobContext> ProcessNormalsFromListOfVector2Async(
const AZStd::span<AZ::Vector2>& inPositions,
const AZStd::span<const AZ::Vector2>& inPositions,
SurfacePointListFillCallback perPositionCallback,
Sampler sampleFilter = Sampler::DEFAULT,
AZStd::shared_ptr<ProcessAsyncParams> params = nullptr) const = 0;
virtual AZStd::shared_ptr<TerrainJobContext> ProcessSurfaceWeightsFromListOfVector2Async(
const AZStd::span<AZ::Vector2>& inPositions,
const AZStd::span<const AZ::Vector2>& inPositions,
SurfacePointListFillCallback perPositionCallback,
Sampler sampleFilter = Sampler::DEFAULT,
AZStd::shared_ptr<ProcessAsyncParams> params = nullptr) const = 0;
virtual AZStd::shared_ptr<TerrainJobContext> ProcessSurfacePointsFromListOfVector2Async(
const AZStd::span<AZ::Vector2>& inPositions,
const AZStd::span<const AZ::Vector2>& inPositions,
SurfacePointListFillCallback perPositionCallback,
Sampler sampleFilter = Sampler::DEFAULT,
AZStd::shared_ptr<ProcessAsyncParams> params = nullptr) const = 0;
@@ -77,21 +77,21 @@ namespace UnitTest
MOCK_CONST_METHOD5(
GetSurfacePointFromFloats, void(float, float, AzFramework::SurfaceData::SurfacePoint&, Sampler, bool*));
MOCK_CONST_METHOD3(
ProcessHeightsFromList, void(const AZStd::span<AZ::Vector3>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler));
ProcessHeightsFromList, void(const AZStd::span<const AZ::Vector3>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler));
MOCK_CONST_METHOD3(
ProcessNormalsFromList, void(const AZStd::span<AZ::Vector3>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler));
ProcessNormalsFromList, void(const AZStd::span<const AZ::Vector3>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler));
MOCK_CONST_METHOD3(
ProcessSurfaceWeightsFromList, void(const AZStd::span<AZ::Vector3>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler));
ProcessSurfaceWeightsFromList, void(const AZStd::span<const AZ::Vector3>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler));
MOCK_CONST_METHOD3(
ProcessSurfacePointsFromList, void(const AZStd::span<AZ::Vector3>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler));
ProcessSurfacePointsFromList, void(const AZStd::span<const AZ::Vector3>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler));
MOCK_CONST_METHOD3(
ProcessHeightsFromListOfVector2, void(const AZStd::span<AZ::Vector2>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler));
ProcessHeightsFromListOfVector2, void(const AZStd::span<const AZ::Vector2>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler));
MOCK_CONST_METHOD3(
ProcessNormalsFromListOfVector2, void(const AZStd::span<AZ::Vector2>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler));
ProcessNormalsFromListOfVector2, void(const AZStd::span<const AZ::Vector2>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler));
MOCK_CONST_METHOD3(
ProcessSurfaceWeightsFromListOfVector2, void(const AZStd::span<AZ::Vector2>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler));
ProcessSurfaceWeightsFromListOfVector2, void(const AZStd::span<const AZ::Vector2>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler));
MOCK_CONST_METHOD3(
ProcessSurfacePointsFromListOfVector2, void(const AZStd::span<AZ::Vector2>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler));
ProcessSurfacePointsFromListOfVector2, void(const AZStd::span<const AZ::Vector2>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler));
MOCK_CONST_METHOD2(
GetNumSamplesFromRegion, AZStd::pair<size_t, size_t>(const AZ::Aabb&, const AZ::Vector2&));
MOCK_CONST_METHOD4(
@@ -107,21 +107,21 @@ namespace UnitTest
MOCK_CONST_METHOD1(
GetClosestIntersection, AzFramework::RenderGeometry::RayResult(const AzFramework::RenderGeometry::RayRequest&));
MOCK_CONST_METHOD4(
ProcessHeightsFromListAsync, AZStd::shared_ptr<TerrainJobContext>(const AZStd::span<AZ::Vector3>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler, AZStd::shared_ptr<ProcessAsyncParams>));
ProcessHeightsFromListAsync, AZStd::shared_ptr<TerrainJobContext>(const AZStd::span<const AZ::Vector3>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler, AZStd::shared_ptr<ProcessAsyncParams>));
MOCK_CONST_METHOD4(
ProcessNormalsFromListAsync, AZStd::shared_ptr<TerrainJobContext>(const AZStd::span<AZ::Vector3>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler, AZStd::shared_ptr<ProcessAsyncParams>));
ProcessNormalsFromListAsync, AZStd::shared_ptr<TerrainJobContext>(const AZStd::span<const AZ::Vector3>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler, AZStd::shared_ptr<ProcessAsyncParams>));
MOCK_CONST_METHOD4(
ProcessSurfaceWeightsFromListAsync, AZStd::shared_ptr<TerrainJobContext>(const AZStd::span<AZ::Vector3>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler, AZStd::shared_ptr<ProcessAsyncParams>));
ProcessSurfaceWeightsFromListAsync, AZStd::shared_ptr<TerrainJobContext>(const AZStd::span<const AZ::Vector3>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler, AZStd::shared_ptr<ProcessAsyncParams>));
MOCK_CONST_METHOD4(
ProcessSurfacePointsFromListAsync, AZStd::shared_ptr<TerrainJobContext>(const AZStd::span<AZ::Vector3>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler, AZStd::shared_ptr<ProcessAsyncParams>));
ProcessSurfacePointsFromListAsync, AZStd::shared_ptr<TerrainJobContext>(const AZStd::span<const AZ::Vector3>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler, AZStd::shared_ptr<ProcessAsyncParams>));
MOCK_CONST_METHOD4(
ProcessHeightsFromListOfVector2Async, AZStd::shared_ptr<TerrainJobContext>(const AZStd::span<AZ::Vector2>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler, AZStd::shared_ptr<ProcessAsyncParams>));
ProcessHeightsFromListOfVector2Async, AZStd::shared_ptr<TerrainJobContext>(const AZStd::span<const AZ::Vector2>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler, AZStd::shared_ptr<ProcessAsyncParams>));
MOCK_CONST_METHOD4(
ProcessNormalsFromListOfVector2Async, AZStd::shared_ptr<TerrainJobContext>(const AZStd::span<AZ::Vector2>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler, AZStd::shared_ptr<ProcessAsyncParams>));
ProcessNormalsFromListOfVector2Async, AZStd::shared_ptr<TerrainJobContext>(const AZStd::span<const AZ::Vector2>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler, AZStd::shared_ptr<ProcessAsyncParams>));
MOCK_CONST_METHOD4(
ProcessSurfaceWeightsFromListOfVector2Async, AZStd::shared_ptr<TerrainJobContext>(const AZStd::span<AZ::Vector2>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler, AZStd::shared_ptr<ProcessAsyncParams>));
ProcessSurfaceWeightsFromListOfVector2Async, AZStd::shared_ptr<TerrainJobContext>(const AZStd::span<const AZ::Vector2>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler, AZStd::shared_ptr<ProcessAsyncParams>));
MOCK_CONST_METHOD4(
ProcessSurfacePointsFromListOfVector2Async, AZStd::shared_ptr<TerrainJobContext>(const AZStd::span<AZ::Vector2>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler, AZStd::shared_ptr<ProcessAsyncParams>));
ProcessSurfacePointsFromListOfVector2Async, AZStd::shared_ptr<TerrainJobContext>(const AZStd::span<const AZ::Vector2>&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler, AZStd::shared_ptr<ProcessAsyncParams>));
MOCK_CONST_METHOD5(
ProcessHeightsFromRegionAsync, AZStd::shared_ptr<TerrainJobContext>(const AZ::Aabb&, const AZ::Vector2&, AzFramework::Terrain::SurfacePointRegionFillCallback, Sampler, AZStd::shared_ptr<ProcessAsyncParams>));
MOCK_CONST_METHOD5(