Unit tests and benchmarks for GetValues() (#6823)
* Benchmarks and tests for Image and Constant GetValues Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Verify GetValues for Perlin and Random Gradients Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Standardized the assert format for GetValues(). Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * More GetValues unit tests and test cleanup Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Fixed typos Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * GetValues() unit tests for surface gradients. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Benchmarks for ShapeAreaFalloff Gradient Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Added benchmarks for all remaining gradients and cleaned up the helper methods. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Renamed class for better report formatting. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Added missing Mocks dependencies for the Editor tests. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>
This commit is contained in:
@@ -141,6 +141,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
AZ::AzTestShared
|
||||
Gem::GradientSignal.Static
|
||||
Gem::LmbrCentral
|
||||
Gem::LmbrCentral.Mocks
|
||||
Gem::GradientSignal.Mocks
|
||||
)
|
||||
|
||||
@@ -160,6 +161,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
Gem::GradientSignal.Tests.Static
|
||||
Gem::GradientSignal.Static
|
||||
Gem::LmbrCentral
|
||||
Gem::LmbrCentral.Mocks
|
||||
Gem::GradientSignal.Mocks
|
||||
)
|
||||
ly_add_googletest(
|
||||
@@ -190,6 +192,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
Gem::GradientSignal.Static
|
||||
Gem::GradientSignal.Editor.Static
|
||||
Gem::LmbrCentral.Editor
|
||||
Gem::LmbrCentral.Mocks
|
||||
)
|
||||
ly_add_googletest(
|
||||
NAME Gem::GradientSignal.Editor.Tests
|
||||
|
||||
@@ -62,22 +62,21 @@ namespace GradientSignal
|
||||
// Reference implementation of GetValues for any gradients that don't have their own optimized implementations.
|
||||
// This is 10%-60% faster than calling GetValue via EBus many times due to the per-call EBus overhead.
|
||||
|
||||
AZ_Assert(
|
||||
positions.size() == outValues.size(), "input and output lists are different sizes (%zu vs %zu).",
|
||||
positions.size(), outValues.size());
|
||||
|
||||
if (positions.size() == outValues.size())
|
||||
if (positions.size() != outValues.size())
|
||||
{
|
||||
GradientSampleParams sampleParams;
|
||||
for (size_t index = 0; index < positions.size(); index++)
|
||||
{
|
||||
sampleParams.m_position = positions[index];
|
||||
AZ_Assert(false, "input and output lists are different sizes (%zu vs %zu).", positions.size(), outValues.size());
|
||||
return;
|
||||
}
|
||||
|
||||
// The const_cast is necessary for now since array_view currently only supports const entries.
|
||||
// If/when array_view is fixed to support non-const, or AZStd::span gets created, the const_cast can get removed.
|
||||
auto& outValue = const_cast<float&>(outValues[index]);
|
||||
outValue = GetValue(sampleParams);
|
||||
}
|
||||
GradientSampleParams sampleParams;
|
||||
for (size_t index = 0; index < positions.size(); index++)
|
||||
{
|
||||
sampleParams.m_position = positions[index];
|
||||
|
||||
// The const_cast is necessary for now since array_view currently only supports const entries.
|
||||
// If/when array_view is fixed to support non-const, or AZStd::span gets created, the const_cast can get removed.
|
||||
auto& outValue = const_cast<float&>(outValues[index]);
|
||||
outValue = GetValue(sampleParams);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ namespace GradientSignal
|
||||
|
||||
if (m_isRequestInProgress)
|
||||
{
|
||||
AZ_ErrorOnce("GradientSignal", !m_isRequestInProgress, "Detected cyclic dependences with gradient entity references");
|
||||
AZ_ErrorOnce("GradientSignal", !m_isRequestInProgress, "Detected cyclic dependencies with gradient entity references");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -197,7 +197,7 @@ namespace GradientSignal
|
||||
|
||||
if (m_isRequestInProgress)
|
||||
{
|
||||
AZ_ErrorOnce("GradientSignal", !m_isRequestInProgress, "Detected cyclic dependences with gradient entity references");
|
||||
AZ_ErrorOnce("GradientSignal", !m_isRequestInProgress, "Detected cyclic dependencies with gradient entity references");
|
||||
ClearOutputValues(outValues);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -16,162 +16,337 @@
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
#include <AzFramework/Asset/AssetCatalogBus.h>
|
||||
|
||||
#include <GradientSignal/Components/ImageGradientComponent.h>
|
||||
#include <GradientSignal/Components/PerlinGradientComponent.h>
|
||||
#include <GradientSignal/Components/RandomGradientComponent.h>
|
||||
#include <GradientSignal/Components/GradientTransformComponent.h>
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
BENCHMARK_DEFINE_F(GradientSignalBenchmarkFixture, BM_ImageGradientEBusGetValue)(benchmark::State& state)
|
||||
class GradientGetValues : public GradientSignalBenchmarkFixture
|
||||
{
|
||||
CreateTestImageGradient(m_testEntity.get());
|
||||
RunEBusGetValueBenchmark(state);
|
||||
}
|
||||
public:
|
||||
// We use an enum to list out the different types of GetValue() benchmarks to run so that way we can condense our test cases
|
||||
// to just take the value in as a benchmark argument and switch on it. Otherwise, we would need to write a different benchmark
|
||||
// function for each test case for each gradient.
|
||||
enum GetValuePermutation : int64_t
|
||||
{
|
||||
EBUS_GET_VALUE,
|
||||
EBUS_GET_VALUES,
|
||||
SAMPLER_GET_VALUE,
|
||||
SAMPLER_GET_VALUES,
|
||||
};
|
||||
|
||||
BENCHMARK_REGISTER_F(GradientSignalBenchmarkFixture, BM_ImageGradientEBusGetValue)
|
||||
->Args({ 1024, 1024 })
|
||||
->Args({ 2048, 2048 })
|
||||
->Args({ 4096, 4096 })
|
||||
// Create an arbitrary size shape for creating our gradients for benchmark runs.
|
||||
const float TestShapeHalfBounds = 128.0f;
|
||||
|
||||
void FillQueryPositions(AZStd::vector<AZ::Vector3>& positions, float height, float width)
|
||||
{
|
||||
size_t index = 0;
|
||||
for (float y = 0.0f; y < height; y += 1.0f)
|
||||
{
|
||||
for (float x = 0.0f; x < width; x += 1.0f)
|
||||
{
|
||||
positions[index++] = AZ::Vector3(x, y, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RunEBusGetValueBenchmark(benchmark::State& state, const AZ::EntityId& gradientId, int64_t queryRange)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(Entity);
|
||||
|
||||
GradientSignal::GradientSampleParams params;
|
||||
|
||||
// Get the height and width ranges for querying from our benchmark parameters
|
||||
const float height = aznumeric_cast<float>(queryRange);
|
||||
const float width = aznumeric_cast<float>(queryRange);
|
||||
|
||||
// Call GetValue() on the EBus for every height and width in our ranges.
|
||||
for (auto _ : state)
|
||||
{
|
||||
for (float y = 0.0f; y < height; y += 1.0f)
|
||||
{
|
||||
for (float x = 0.0f; x < width; x += 1.0f)
|
||||
{
|
||||
float value = 0.0f;
|
||||
params.m_position = AZ::Vector3(x, y, 0.0f);
|
||||
GradientSignal::GradientRequestBus::EventResult(
|
||||
value, gradientId, &GradientSignal::GradientRequestBus::Events::GetValue, params);
|
||||
benchmark::DoNotOptimize(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RunEBusGetValuesBenchmark(benchmark::State& state, const AZ::EntityId& gradientId, int64_t queryRange)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(Entity);
|
||||
|
||||
// Get the height and width ranges for querying from our benchmark parameters
|
||||
float height = aznumeric_cast<float>(queryRange);
|
||||
float width = aznumeric_cast<float>(queryRange);
|
||||
int64_t totalQueryPoints = queryRange * queryRange;
|
||||
|
||||
// Call GetValues() for every height and width in our ranges.
|
||||
for (auto _ : state)
|
||||
{
|
||||
// Set up our vector of query positions. This is done inside the benchmark timing since we're counting the work to create
|
||||
// each query position in the single GetValue() call benchmarks, and will make the timing more directly comparable.
|
||||
AZStd::vector<AZ::Vector3> positions(totalQueryPoints);
|
||||
FillQueryPositions(positions, height, width);
|
||||
|
||||
// Query and get the results.
|
||||
AZStd::vector<float> results(totalQueryPoints);
|
||||
GradientSignal::GradientRequestBus::Event(
|
||||
gradientId, &GradientSignal::GradientRequestBus::Events::GetValues, positions, results);
|
||||
}
|
||||
}
|
||||
|
||||
void RunSamplerGetValueBenchmark(benchmark::State& state, const AZ::EntityId& gradientId, int64_t queryRange)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(Entity);
|
||||
|
||||
// Create a gradient sampler to use for querying our gradient.
|
||||
GradientSignal::GradientSampler gradientSampler;
|
||||
gradientSampler.m_gradientId = gradientId;
|
||||
|
||||
// Get the height and width ranges for querying from our benchmark parameters
|
||||
const float height = aznumeric_cast<float>(queryRange);
|
||||
const float width = aznumeric_cast<float>(queryRange);
|
||||
|
||||
// Call GetValue() through the GradientSampler for every height and width in our ranges.
|
||||
for (auto _ : state)
|
||||
{
|
||||
for (float y = 0.0f; y < height; y += 1.0f)
|
||||
{
|
||||
for (float x = 0.0f; x < width; x += 1.0f)
|
||||
{
|
||||
GradientSignal::GradientSampleParams params;
|
||||
params.m_position = AZ::Vector3(x, y, 0.0f);
|
||||
float value = gradientSampler.GetValue(params);
|
||||
benchmark::DoNotOptimize(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RunSamplerGetValuesBenchmark(benchmark::State& state, const AZ::EntityId& gradientId, int64_t queryRange)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(Entity);
|
||||
|
||||
// Create a gradient sampler to use for querying our gradient.
|
||||
GradientSignal::GradientSampler gradientSampler;
|
||||
gradientSampler.m_gradientId = gradientId;
|
||||
|
||||
// Get the height and width ranges for querying from our benchmark parameters
|
||||
const float height = aznumeric_cast<float>(queryRange);
|
||||
const float width = aznumeric_cast<float>(queryRange);
|
||||
const int64_t totalQueryPoints = queryRange * queryRange;
|
||||
|
||||
// Call GetValues() through the GradientSampler for every height and width in our ranges.
|
||||
for (auto _ : state)
|
||||
{
|
||||
// Set up our vector of query positions. This is done inside the benchmark timing since we're counting the work to create
|
||||
// each query position in the single GetValue() call benchmarks, and will make the timing more directly comparable.
|
||||
AZStd::vector<AZ::Vector3> positions(totalQueryPoints);
|
||||
FillQueryPositions(positions, height, width);
|
||||
|
||||
// Query and get the results.
|
||||
AZStd::vector<float> results(totalQueryPoints);
|
||||
gradientSampler.GetValues(positions, results);
|
||||
}
|
||||
}
|
||||
|
||||
void RunGetValueOrGetValuesBenchmark(benchmark::State& state, const AZ::EntityId& gradientId)
|
||||
{
|
||||
switch (state.range(0))
|
||||
{
|
||||
case GetValuePermutation::EBUS_GET_VALUE:
|
||||
RunEBusGetValueBenchmark(state, gradientId, state.range(1));
|
||||
break;
|
||||
case GetValuePermutation::EBUS_GET_VALUES:
|
||||
RunEBusGetValuesBenchmark(state, gradientId, state.range(1));
|
||||
break;
|
||||
case GetValuePermutation::SAMPLER_GET_VALUE:
|
||||
RunSamplerGetValueBenchmark(state, gradientId, state.range(1));
|
||||
break;
|
||||
case GetValuePermutation::SAMPLER_GET_VALUES:
|
||||
RunSamplerGetValuesBenchmark(state, gradientId, state.range(1));
|
||||
break;
|
||||
default:
|
||||
AZ_Assert(false, "Benchmark permutation type not supported.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Because there's no good way to label different enums in the output results (they just appear as integer values), we work around it by
|
||||
// registering one set of benchmark runs for each enum value and use ArgNames() to give it a friendly name in the results.
|
||||
#define GRADIENT_SIGNAL_GET_VALUES_BENCHMARK_REGISTER_F(Fixture, Func) \
|
||||
BENCHMARK_REGISTER_F(Fixture, Func) \
|
||||
->Args({ GradientGetValues::GetValuePermutation::EBUS_GET_VALUE, 1024 }) \
|
||||
->Args({ GradientGetValues::GetValuePermutation::EBUS_GET_VALUE, 2048 }) \
|
||||
->Args({ GradientGetValues::GetValuePermutation::EBUS_GET_VALUE, 4096 }) \
|
||||
->ArgNames({ "EbusGetValue", "size" }) \
|
||||
->Unit(::benchmark::kMillisecond); \
|
||||
BENCHMARK_REGISTER_F(Fixture, Func) \
|
||||
->Args({ GradientGetValues::GetValuePermutation::EBUS_GET_VALUES, 1024 }) \
|
||||
->Args({ GradientGetValues::GetValuePermutation::EBUS_GET_VALUES, 2048 }) \
|
||||
->Args({ GradientGetValues::GetValuePermutation::EBUS_GET_VALUES, 4096 }) \
|
||||
->ArgNames({ "EbusGetValues", "size" }) \
|
||||
->Unit(::benchmark::kMillisecond); \
|
||||
BENCHMARK_REGISTER_F(Fixture, Func) \
|
||||
->Args({ GradientGetValues::GetValuePermutation::SAMPLER_GET_VALUE, 1024 }) \
|
||||
->Args({ GradientGetValues::GetValuePermutation::SAMPLER_GET_VALUE, 2048 }) \
|
||||
->Args({ GradientGetValues::GetValuePermutation::SAMPLER_GET_VALUE, 4096 }) \
|
||||
->ArgNames({ "SamplerGetValue", "size" }) \
|
||||
->Unit(::benchmark::kMillisecond); \
|
||||
BENCHMARK_REGISTER_F(Fixture, Func) \
|
||||
->Args({ GradientGetValues::GetValuePermutation::SAMPLER_GET_VALUES, 1024 }) \
|
||||
->Args({ GradientGetValues::GetValuePermutation::SAMPLER_GET_VALUES, 2048 }) \
|
||||
->Args({ GradientGetValues::GetValuePermutation::SAMPLER_GET_VALUES, 4096 }) \
|
||||
->ArgNames({ "SamplerGetValues", "size" }) \
|
||||
->Unit(::benchmark::kMillisecond);
|
||||
|
||||
BENCHMARK_DEFINE_F(GradientSignalBenchmarkFixture, BM_ImageGradientEBusGetValues)(benchmark::State& state)
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Base Gradients
|
||||
|
||||
BENCHMARK_DEFINE_F(GradientGetValues, BM_ConstantGradient)(benchmark::State& state)
|
||||
{
|
||||
CreateTestImageGradient(m_testEntity.get());
|
||||
RunEBusGetValuesBenchmark(state);
|
||||
auto entity = BuildTestConstantGradient(TestShapeHalfBounds);
|
||||
RunGetValueOrGetValuesBenchmark(state, entity->GetId());
|
||||
}
|
||||
|
||||
BENCHMARK_REGISTER_F(GradientSignalBenchmarkFixture, BM_ImageGradientEBusGetValues)
|
||||
->Args({ 1024, 1024 })
|
||||
->Args({ 2048, 2048 })
|
||||
->Args({ 4096, 4096 })
|
||||
->Unit(::benchmark::kMillisecond);
|
||||
|
||||
BENCHMARK_DEFINE_F(GradientSignalBenchmarkFixture, BM_ImageGradientSamplerGetValue)(benchmark::State& state)
|
||||
BENCHMARK_DEFINE_F(GradientGetValues, BM_ImageGradient)(benchmark::State& state)
|
||||
{
|
||||
CreateTestImageGradient(m_testEntity.get());
|
||||
RunSamplerGetValueBenchmark(state);
|
||||
auto entity = BuildTestImageGradient(TestShapeHalfBounds);
|
||||
RunGetValueOrGetValuesBenchmark(state, entity->GetId());
|
||||
}
|
||||
|
||||
BENCHMARK_REGISTER_F(GradientSignalBenchmarkFixture, BM_ImageGradientSamplerGetValue)
|
||||
->Args({ 1024, 1024 })
|
||||
->Args({ 2048, 2048 })
|
||||
->Args({ 4096, 4096 })
|
||||
->Unit(::benchmark::kMillisecond);
|
||||
|
||||
BENCHMARK_DEFINE_F(GradientSignalBenchmarkFixture, BM_ImageGradientSamplerGetValues)(benchmark::State& state)
|
||||
BENCHMARK_DEFINE_F(GradientGetValues, BM_PerlinGradient)(benchmark::State& state)
|
||||
{
|
||||
CreateTestImageGradient(m_testEntity.get());
|
||||
RunSamplerGetValuesBenchmark(state);
|
||||
auto entity = BuildTestPerlinGradient(TestShapeHalfBounds);
|
||||
RunGetValueOrGetValuesBenchmark(state, entity->GetId());
|
||||
}
|
||||
|
||||
BENCHMARK_REGISTER_F(GradientSignalBenchmarkFixture, BM_ImageGradientSamplerGetValues)
|
||||
->Args({ 1024, 1024 })
|
||||
->Args({ 2048, 2048 })
|
||||
->Args({ 4096, 4096 })
|
||||
->Unit(::benchmark::kMillisecond);
|
||||
|
||||
BENCHMARK_DEFINE_F(GradientSignalBenchmarkFixture, BM_PerlinGradientEBusGetValue)(benchmark::State& state)
|
||||
BENCHMARK_DEFINE_F(GradientGetValues, BM_RandomGradient)(benchmark::State& state)
|
||||
{
|
||||
CreateTestPerlinGradient(m_testEntity.get());
|
||||
RunEBusGetValueBenchmark(state);
|
||||
auto entity = BuildTestRandomGradient(TestShapeHalfBounds);
|
||||
RunGetValueOrGetValuesBenchmark(state, entity->GetId());
|
||||
}
|
||||
|
||||
BENCHMARK_REGISTER_F(GradientSignalBenchmarkFixture, BM_PerlinGradientEBusGetValue)
|
||||
->Args({ 1024, 1024 })
|
||||
->Args({ 2048, 2048 })
|
||||
->Args({ 4096, 4096 })
|
||||
->Unit(::benchmark::kMillisecond);
|
||||
|
||||
BENCHMARK_DEFINE_F(GradientSignalBenchmarkFixture, BM_PerlinGradientEBusGetValues)(benchmark::State& state)
|
||||
BENCHMARK_DEFINE_F(GradientGetValues, BM_ShapeAreaFalloffGradient)(benchmark::State& state)
|
||||
{
|
||||
CreateTestPerlinGradient(m_testEntity.get());
|
||||
RunEBusGetValuesBenchmark(state);
|
||||
auto entity = BuildTestShapeAreaFalloffGradient(TestShapeHalfBounds);
|
||||
RunGetValueOrGetValuesBenchmark(state, entity->GetId());
|
||||
}
|
||||
|
||||
BENCHMARK_REGISTER_F(GradientSignalBenchmarkFixture, BM_PerlinGradientEBusGetValues)
|
||||
->Args({ 1024, 1024 })
|
||||
->Args({ 2048, 2048 })
|
||||
->Args({ 4096, 4096 })
|
||||
->Unit(::benchmark::kMillisecond);
|
||||
GRADIENT_SIGNAL_GET_VALUES_BENCHMARK_REGISTER_F(GradientGetValues, BM_ConstantGradient);
|
||||
GRADIENT_SIGNAL_GET_VALUES_BENCHMARK_REGISTER_F(GradientGetValues, BM_ImageGradient);
|
||||
GRADIENT_SIGNAL_GET_VALUES_BENCHMARK_REGISTER_F(GradientGetValues, BM_PerlinGradient);
|
||||
GRADIENT_SIGNAL_GET_VALUES_BENCHMARK_REGISTER_F(GradientGetValues, BM_RandomGradient);
|
||||
GRADIENT_SIGNAL_GET_VALUES_BENCHMARK_REGISTER_F(GradientGetValues, BM_ShapeAreaFalloffGradient);
|
||||
|
||||
BENCHMARK_DEFINE_F(GradientSignalBenchmarkFixture, BM_PerlinGradientSamplerGetValue)(benchmark::State& state)
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Gradient Modifiers
|
||||
|
||||
BENCHMARK_DEFINE_F(GradientGetValues, BM_DitherGradient)(benchmark::State& state)
|
||||
{
|
||||
CreateTestPerlinGradient(m_testEntity.get());
|
||||
RunSamplerGetValueBenchmark(state);
|
||||
auto baseEntity = BuildTestRandomGradient(TestShapeHalfBounds);
|
||||
auto entity = BuildTestDitherGradient(TestShapeHalfBounds, baseEntity->GetId());
|
||||
RunGetValueOrGetValuesBenchmark(state, entity->GetId());
|
||||
}
|
||||
|
||||
BENCHMARK_REGISTER_F(GradientSignalBenchmarkFixture, BM_PerlinGradientSamplerGetValue)
|
||||
->Args({ 1024, 1024 })
|
||||
->Args({ 2048, 2048 })
|
||||
->Args({ 4096, 4096 })
|
||||
->Unit(::benchmark::kMillisecond);
|
||||
|
||||
BENCHMARK_DEFINE_F(GradientSignalBenchmarkFixture, BM_PerlinGradientSamplerGetValues)(benchmark::State& state)
|
||||
BENCHMARK_DEFINE_F(GradientGetValues, BM_InvertGradient)(benchmark::State& state)
|
||||
{
|
||||
CreateTestPerlinGradient(m_testEntity.get());
|
||||
RunSamplerGetValuesBenchmark(state);
|
||||
auto baseEntity = BuildTestRandomGradient(TestShapeHalfBounds);
|
||||
auto entity = BuildTestDitherGradient(TestShapeHalfBounds, baseEntity->GetId());
|
||||
RunGetValueOrGetValuesBenchmark(state, entity->GetId());
|
||||
}
|
||||
|
||||
BENCHMARK_REGISTER_F(GradientSignalBenchmarkFixture, BM_PerlinGradientSamplerGetValues)
|
||||
->Args({ 1024, 1024 })
|
||||
->Args({ 2048, 2048 })
|
||||
->Args({ 4096, 4096 })
|
||||
->Unit(::benchmark::kMillisecond);
|
||||
|
||||
BENCHMARK_DEFINE_F(GradientSignalBenchmarkFixture, BM_RandomGradientEBusGetValue)(benchmark::State& state)
|
||||
BENCHMARK_DEFINE_F(GradientGetValues, BM_LevelsGradient)(benchmark::State& state)
|
||||
{
|
||||
CreateTestRandomGradient(m_testEntity.get());
|
||||
RunEBusGetValueBenchmark(state);
|
||||
auto baseEntity = BuildTestRandomGradient(TestShapeHalfBounds);
|
||||
auto entity = BuildTestLevelsGradient(TestShapeHalfBounds, baseEntity->GetId());
|
||||
RunGetValueOrGetValuesBenchmark(state, entity->GetId());
|
||||
}
|
||||
|
||||
BENCHMARK_REGISTER_F(GradientSignalBenchmarkFixture, BM_RandomGradientEBusGetValue)
|
||||
->Args({ 1024, 1024 })
|
||||
->Args({ 2048, 2048 })
|
||||
->Args({ 4096, 4096 })
|
||||
->Unit(::benchmark::kMillisecond);
|
||||
|
||||
BENCHMARK_DEFINE_F(GradientSignalBenchmarkFixture, BM_RandomGradientEBusGetValues)(benchmark::State& state)
|
||||
BENCHMARK_DEFINE_F(GradientGetValues, BM_MixedGradient)(benchmark::State& state)
|
||||
{
|
||||
CreateTestRandomGradient(m_testEntity.get());
|
||||
RunEBusGetValuesBenchmark(state);
|
||||
auto baseEntity = BuildTestRandomGradient(TestShapeHalfBounds);
|
||||
auto mixedEntity = BuildTestConstantGradient(TestShapeHalfBounds);
|
||||
auto entity = BuildTestMixedGradient(TestShapeHalfBounds, baseEntity->GetId(), mixedEntity->GetId());
|
||||
RunGetValueOrGetValuesBenchmark(state, entity->GetId());
|
||||
}
|
||||
|
||||
BENCHMARK_REGISTER_F(GradientSignalBenchmarkFixture, BM_RandomGradientEBusGetValues)
|
||||
->Args({ 1024, 1024 })
|
||||
->Args({ 2048, 2048 })
|
||||
->Args({ 4096, 4096 })
|
||||
->Unit(::benchmark::kMillisecond);
|
||||
|
||||
BENCHMARK_DEFINE_F(GradientSignalBenchmarkFixture, BM_RandomGradientSamplerGetValue)(benchmark::State& state)
|
||||
BENCHMARK_DEFINE_F(GradientGetValues, BM_PosterizeGradient)(benchmark::State& state)
|
||||
{
|
||||
CreateTestRandomGradient(m_testEntity.get());
|
||||
RunSamplerGetValueBenchmark(state);
|
||||
auto baseEntity = BuildTestRandomGradient(TestShapeHalfBounds);
|
||||
auto entity = BuildTestPosterizeGradient(TestShapeHalfBounds, baseEntity->GetId());
|
||||
RunGetValueOrGetValuesBenchmark(state, entity->GetId());
|
||||
}
|
||||
|
||||
BENCHMARK_REGISTER_F(GradientSignalBenchmarkFixture, BM_RandomGradientSamplerGetValue)
|
||||
->Args({ 1024, 1024 })
|
||||
->Args({ 2048, 2048 })
|
||||
->Args({ 4096, 4096 })
|
||||
->Unit(::benchmark::kMillisecond);
|
||||
|
||||
BENCHMARK_DEFINE_F(GradientSignalBenchmarkFixture, BM_RandomGradientSamplerGetValues)(benchmark::State& state)
|
||||
BENCHMARK_DEFINE_F(GradientGetValues, BM_ReferenceGradient)(benchmark::State& state)
|
||||
{
|
||||
CreateTestRandomGradient(m_testEntity.get());
|
||||
RunSamplerGetValuesBenchmark(state);
|
||||
auto baseEntity = BuildTestRandomGradient(TestShapeHalfBounds);
|
||||
auto entity = BuildTestReferenceGradient(TestShapeHalfBounds, baseEntity->GetId());
|
||||
RunGetValueOrGetValuesBenchmark(state, entity->GetId());
|
||||
}
|
||||
|
||||
BENCHMARK_REGISTER_F(GradientSignalBenchmarkFixture, BM_RandomGradientSamplerGetValues)
|
||||
->Args({ 1024, 1024 })
|
||||
->Args({ 2048, 2048 })
|
||||
->Args({ 4096, 4096 })
|
||||
->Unit(::benchmark::kMillisecond);
|
||||
BENCHMARK_DEFINE_F(GradientGetValues, BM_SmoothStepGradient)(benchmark::State& state)
|
||||
{
|
||||
auto baseEntity = BuildTestRandomGradient(TestShapeHalfBounds);
|
||||
auto entity = BuildTestSmoothStepGradient(TestShapeHalfBounds, baseEntity->GetId());
|
||||
RunGetValueOrGetValuesBenchmark(state, entity->GetId());
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(GradientGetValues, BM_ThresholdGradient)(benchmark::State& state)
|
||||
{
|
||||
auto baseEntity = BuildTestRandomGradient(TestShapeHalfBounds);
|
||||
auto entity = BuildTestThresholdGradient(TestShapeHalfBounds, baseEntity->GetId());
|
||||
RunGetValueOrGetValuesBenchmark(state, entity->GetId());
|
||||
}
|
||||
|
||||
GRADIENT_SIGNAL_GET_VALUES_BENCHMARK_REGISTER_F(GradientGetValues, BM_DitherGradient);
|
||||
GRADIENT_SIGNAL_GET_VALUES_BENCHMARK_REGISTER_F(GradientGetValues, BM_InvertGradient);
|
||||
GRADIENT_SIGNAL_GET_VALUES_BENCHMARK_REGISTER_F(GradientGetValues, BM_LevelsGradient);
|
||||
GRADIENT_SIGNAL_GET_VALUES_BENCHMARK_REGISTER_F(GradientGetValues, BM_MixedGradient);
|
||||
GRADIENT_SIGNAL_GET_VALUES_BENCHMARK_REGISTER_F(GradientGetValues, BM_PosterizeGradient);
|
||||
GRADIENT_SIGNAL_GET_VALUES_BENCHMARK_REGISTER_F(GradientGetValues, BM_ReferenceGradient);
|
||||
GRADIENT_SIGNAL_GET_VALUES_BENCHMARK_REGISTER_F(GradientGetValues, BM_SmoothStepGradient);
|
||||
GRADIENT_SIGNAL_GET_VALUES_BENCHMARK_REGISTER_F(GradientGetValues, BM_ThresholdGradient);
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Surface Gradients
|
||||
|
||||
BENCHMARK_DEFINE_F(GradientGetValues, BM_SurfaceAltitudeGradient)(benchmark::State& state)
|
||||
{
|
||||
auto mockSurfaceDataSystem =
|
||||
CreateMockSurfaceDataSystem(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-TestShapeHalfBounds), AZ::Vector3(TestShapeHalfBounds)));
|
||||
|
||||
auto entity = BuildTestSurfaceAltitudeGradient(TestShapeHalfBounds);
|
||||
RunGetValueOrGetValuesBenchmark(state, entity->GetId());
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(GradientGetValues, BM_SurfaceMaskGradient)(benchmark::State& state)
|
||||
{
|
||||
auto mockSurfaceDataSystem =
|
||||
CreateMockSurfaceDataSystem(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-TestShapeHalfBounds), AZ::Vector3(TestShapeHalfBounds)));
|
||||
|
||||
auto entity = BuildTestSurfaceMaskGradient(TestShapeHalfBounds);
|
||||
RunGetValueOrGetValuesBenchmark(state, entity->GetId());
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(GradientGetValues, BM_SurfaceSlopeGradient)(benchmark::State& state)
|
||||
{
|
||||
auto mockSurfaceDataSystem =
|
||||
CreateMockSurfaceDataSystem(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-TestShapeHalfBounds), AZ::Vector3(TestShapeHalfBounds)));
|
||||
|
||||
auto entity = BuildTestSurfaceSlopeGradient(TestShapeHalfBounds);
|
||||
RunGetValueOrGetValuesBenchmark(state, entity->GetId());
|
||||
}
|
||||
|
||||
GRADIENT_SIGNAL_GET_VALUES_BENCHMARK_REGISTER_F(GradientGetValues, BM_SurfaceAltitudeGradient);
|
||||
GRADIENT_SIGNAL_GET_VALUES_BENCHMARK_REGISTER_F(GradientGetValues, BM_SurfaceMaskGradient);
|
||||
GRADIENT_SIGNAL_GET_VALUES_BENCHMARK_REGISTER_F(GradientGetValues, BM_SurfaceSlopeGradient);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <Tests/GradientSignalTestFixtures.h>
|
||||
#include <AzTest/AzTest.h>
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
struct GradientSignalGetValuesTestsFixture
|
||||
: public GradientSignalTest
|
||||
{
|
||||
// Create an arbitrary size shape for comparing values within. It should be large enough that we detect any value anomalies
|
||||
// but small enough that the tests run quickly.
|
||||
const float TestShapeHalfBounds = 128.0f;
|
||||
|
||||
void CompareGetValueAndGetValues(AZ::EntityId gradientEntityId)
|
||||
{
|
||||
// Create a gradient sampler and run through a series of points to see if they match expectations.
|
||||
|
||||
const AZ::Aabb queryRegion = AZ::Aabb::CreateFromMinMax(AZ::Vector3(-TestShapeHalfBounds), AZ::Vector3(TestShapeHalfBounds));
|
||||
const AZ::Vector2 stepSize(1.0f, 1.0f);
|
||||
|
||||
GradientSignal::GradientSampler gradientSampler;
|
||||
gradientSampler.m_gradientId = gradientEntityId;
|
||||
|
||||
const size_t numSamplesX = aznumeric_cast<size_t>(ceil(queryRegion.GetExtents().GetX() / stepSize.GetX()));
|
||||
const size_t numSamplesY = aznumeric_cast<size_t>(ceil(queryRegion.GetExtents().GetY() / stepSize.GetY()));
|
||||
|
||||
// Build up the list of positions to query.
|
||||
AZStd::vector<AZ::Vector3> positions(numSamplesX * numSamplesY);
|
||||
size_t index = 0;
|
||||
for (size_t yIndex = 0; yIndex < numSamplesY; yIndex++)
|
||||
{
|
||||
float y = queryRegion.GetMin().GetY() + (stepSize.GetY() * yIndex);
|
||||
for (size_t xIndex = 0; xIndex < numSamplesX; xIndex++)
|
||||
{
|
||||
float x = queryRegion.GetMin().GetX() + (stepSize.GetX() * xIndex);
|
||||
positions[index++] = AZ::Vector3(x, y, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the results from GetValues
|
||||
AZStd::vector<float> results(numSamplesX * numSamplesY);
|
||||
gradientSampler.GetValues(positions, results);
|
||||
|
||||
// For each position, call GetValue and verify that the values match.
|
||||
for (size_t positionIndex = 0; positionIndex < positions.size(); positionIndex++)
|
||||
{
|
||||
GradientSignal::GradientSampleParams params;
|
||||
params.m_position = positions[positionIndex];
|
||||
float value = gradientSampler.GetValue(params);
|
||||
|
||||
// We use ASSERT_EQ instead of EXPECT_EQ because if one value doesn't match, they probably all won't, so there's no reason
|
||||
// to keep running and printing failures for every value.
|
||||
ASSERT_EQ(value, results[positionIndex]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(GradientSignalGetValuesTestsFixture, ImageGradientComponent_VerifyGetValueAndGetValuesMatch)
|
||||
{
|
||||
auto entity = BuildTestImageGradient(TestShapeHalfBounds);
|
||||
CompareGetValueAndGetValues(entity->GetId());
|
||||
}
|
||||
|
||||
TEST_F(GradientSignalGetValuesTestsFixture, PerlinGradientComponent_VerifyGetValueAndGetValuesMatch)
|
||||
{
|
||||
auto entity = BuildTestPerlinGradient(TestShapeHalfBounds);
|
||||
CompareGetValueAndGetValues(entity->GetId());
|
||||
}
|
||||
|
||||
TEST_F(GradientSignalGetValuesTestsFixture, RandomGradientComponent_VerifyGetValueAndGetValuesMatch)
|
||||
{
|
||||
auto entity = BuildTestRandomGradient(TestShapeHalfBounds);
|
||||
CompareGetValueAndGetValues(entity->GetId());
|
||||
}
|
||||
|
||||
TEST_F(GradientSignalGetValuesTestsFixture, ConstantGradientComponent_VerifyGetValueAndGetValuesMatch)
|
||||
{
|
||||
auto entity = BuildTestConstantGradient(TestShapeHalfBounds);
|
||||
CompareGetValueAndGetValues(entity->GetId());
|
||||
}
|
||||
|
||||
TEST_F(GradientSignalGetValuesTestsFixture, ShapeAreaFalloffGradientComponent_VerifyGetValueAndGetValuesMatch)
|
||||
{
|
||||
auto entity = BuildTestShapeAreaFalloffGradient(TestShapeHalfBounds);
|
||||
CompareGetValueAndGetValues(entity->GetId());
|
||||
}
|
||||
|
||||
TEST_F(GradientSignalGetValuesTestsFixture, DitherGradientComponent_VerifyGetValueAndGetValuesMatch)
|
||||
{
|
||||
auto baseEntity = BuildTestRandomGradient(TestShapeHalfBounds);
|
||||
|
||||
auto entity = BuildTestDitherGradient(TestShapeHalfBounds, baseEntity->GetId());
|
||||
CompareGetValueAndGetValues(entity->GetId());
|
||||
}
|
||||
|
||||
TEST_F(GradientSignalGetValuesTestsFixture, InvertGradientComponent_VerifyGetValueAndGetValuesMatch)
|
||||
{
|
||||
auto baseEntity = BuildTestRandomGradient(TestShapeHalfBounds);
|
||||
auto entity = BuildTestInvertGradient(TestShapeHalfBounds, baseEntity->GetId());
|
||||
CompareGetValueAndGetValues(entity->GetId());
|
||||
}
|
||||
|
||||
TEST_F(GradientSignalGetValuesTestsFixture, LevelsGradientComponent_VerifyGetValueAndGetValuesMatch)
|
||||
{
|
||||
auto baseEntity = BuildTestRandomGradient(TestShapeHalfBounds);
|
||||
auto entity = BuildTestLevelsGradient(TestShapeHalfBounds, baseEntity->GetId());
|
||||
CompareGetValueAndGetValues(entity->GetId());
|
||||
}
|
||||
|
||||
TEST_F(GradientSignalGetValuesTestsFixture, MixedGradientComponent_VerifyGetValueAndGetValuesMatch)
|
||||
{
|
||||
auto baseEntity = BuildTestRandomGradient(TestShapeHalfBounds);
|
||||
auto mixedEntity = BuildTestConstantGradient(TestShapeHalfBounds);
|
||||
auto entity = BuildTestMixedGradient(TestShapeHalfBounds, baseEntity->GetId(), mixedEntity->GetId());
|
||||
CompareGetValueAndGetValues(entity->GetId());
|
||||
}
|
||||
|
||||
TEST_F(GradientSignalGetValuesTestsFixture, PosterizeGradientComponent_VerifyGetValueAndGetValuesMatch)
|
||||
{
|
||||
auto baseEntity = BuildTestRandomGradient(TestShapeHalfBounds);
|
||||
auto entity = BuildTestPosterizeGradient(TestShapeHalfBounds, baseEntity->GetId());
|
||||
CompareGetValueAndGetValues(entity->GetId());
|
||||
}
|
||||
|
||||
TEST_F(GradientSignalGetValuesTestsFixture, ReferenceGradientComponent_VerifyGetValueAndGetValuesMatch)
|
||||
{
|
||||
auto baseEntity = BuildTestRandomGradient(TestShapeHalfBounds);
|
||||
auto entity = BuildTestReferenceGradient(TestShapeHalfBounds, baseEntity->GetId());
|
||||
CompareGetValueAndGetValues(entity->GetId());
|
||||
}
|
||||
|
||||
TEST_F(GradientSignalGetValuesTestsFixture, SmoothStepGradientComponent_VerifyGetValueAndGetValuesMatch)
|
||||
{
|
||||
auto baseEntity = BuildTestRandomGradient(TestShapeHalfBounds);
|
||||
auto entity = BuildTestSmoothStepGradient(TestShapeHalfBounds, baseEntity->GetId());
|
||||
CompareGetValueAndGetValues(entity->GetId());
|
||||
}
|
||||
|
||||
TEST_F(GradientSignalGetValuesTestsFixture, ThresholdGradientComponent_VerifyGetValueAndGetValuesMatch)
|
||||
{
|
||||
auto baseEntity = BuildTestRandomGradient(TestShapeHalfBounds);
|
||||
auto entity = BuildTestThresholdGradient(TestShapeHalfBounds, baseEntity->GetId());
|
||||
CompareGetValueAndGetValues(entity->GetId());
|
||||
}
|
||||
|
||||
TEST_F(GradientSignalGetValuesTestsFixture, SurfaceAltitudeGradientComponent_VerifyGetValueAndGetValuesMatch)
|
||||
{
|
||||
auto mockSurfaceDataSystem =
|
||||
CreateMockSurfaceDataSystem(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-TestShapeHalfBounds), AZ::Vector3(TestShapeHalfBounds)));
|
||||
|
||||
auto entity = BuildTestSurfaceAltitudeGradient(TestShapeHalfBounds);
|
||||
CompareGetValueAndGetValues(entity->GetId());
|
||||
}
|
||||
|
||||
TEST_F(GradientSignalGetValuesTestsFixture, SurfaceMaskGradientComponent_VerifyGetValueAndGetValuesMatch)
|
||||
{
|
||||
auto mockSurfaceDataSystem =
|
||||
CreateMockSurfaceDataSystem(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-TestShapeHalfBounds), AZ::Vector3(TestShapeHalfBounds)));
|
||||
|
||||
auto entity = BuildTestSurfaceMaskGradient(TestShapeHalfBounds);
|
||||
CompareGetValueAndGetValues(entity->GetId());
|
||||
}
|
||||
|
||||
TEST_F(GradientSignalGetValuesTestsFixture, SurfaceSlopeGradientComponent_VerifyGetValueAndGetValuesMatch)
|
||||
{
|
||||
auto mockSurfaceDataSystem =
|
||||
CreateMockSurfaceDataSystem(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-TestShapeHalfBounds), AZ::Vector3(TestShapeHalfBounds)));
|
||||
|
||||
auto entity = BuildTestSurfaceSlopeGradient(TestShapeHalfBounds);
|
||||
CompareGetValueAndGetValues(entity->GetId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -417,7 +417,6 @@ namespace UnitTest
|
||||
TestFixedDataSampler(expectedOutput, dataSize, entity->GetId());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -371,12 +371,9 @@ namespace UnitTest
|
||||
const AZ::EntityId id = mockReference->GetId();
|
||||
MockGradientArrayRequestsBus mockGradientRequestsBus(id, inputData, dataSize);
|
||||
|
||||
GradientSignal::ReferenceGradientConfig config;
|
||||
config.m_gradientSampler.m_gradientId = mockReference->GetId();
|
||||
|
||||
auto entity = CreateEntity();
|
||||
CreateComponent<GradientSignal::ReferenceGradientComponent>(entity.get(), config);
|
||||
ActivateEntity(entity.get());
|
||||
// Create a reference gradient with an arbitrary box shape on it.
|
||||
const float HalfBounds = 64.0f;
|
||||
auto entity = BuildTestReferenceGradient(HalfBounds, mockReference->GetId());
|
||||
|
||||
TestFixedDataSampler(expectedOutput, dataSize, entity->GetId());
|
||||
}
|
||||
@@ -385,10 +382,9 @@ namespace UnitTest
|
||||
{
|
||||
// Verify that gradient references can validate and disconnect cyclic connections
|
||||
|
||||
auto constantGradientEntity = CreateEntity();
|
||||
GradientSignal::ConstantGradientConfig constantGradientConfig;
|
||||
CreateComponent<GradientSignal::ConstantGradientComponent>(constantGradientEntity.get(), constantGradientConfig);
|
||||
ActivateEntity(constantGradientEntity.get());
|
||||
// Create a constant gradient with an arbitrary box shape on it.
|
||||
const float HalfBounds = 64.0f;
|
||||
auto constantGradientEntity = BuildTestConstantGradient(HalfBounds);
|
||||
|
||||
// Verify cyclic reference test passes when pointing to gradient generator entity
|
||||
auto referenceGradientEntity1 = CreateEntity();
|
||||
|
||||
@@ -212,12 +212,9 @@ namespace UnitTest
|
||||
const AZ::EntityId id = entityMock->GetId();
|
||||
UnitTest::MockGradientArrayRequestsBus mockGradientRequestsBus(id, inputData, dataSize);
|
||||
|
||||
GradientSignal::InvertGradientConfig config;
|
||||
config.m_gradientSampler.m_gradientId = entityMock->GetId();
|
||||
|
||||
auto entity = CreateEntity();
|
||||
CreateComponent<GradientSignal::InvertGradientComponent>(entity.get(), config);
|
||||
ActivateEntity(entity.get());
|
||||
// Create the entity with an arbitrarily-sized box.
|
||||
const float HalfBounds = 64.0f;
|
||||
auto entity = BuildTestInvertGradient(HalfBounds, entityMock->GetId());
|
||||
|
||||
TestFixedDataSampler(expectedOutput, dataSize, entity->GetId());
|
||||
}
|
||||
|
||||
@@ -9,10 +9,30 @@
|
||||
|
||||
#include <Tests/GradientSignalTestFixtures.h>
|
||||
|
||||
#include <AzFramework/Components/TransformComponent.h>
|
||||
#include <GradientSignal/Components/GradientTransformComponent.h>
|
||||
|
||||
// Base gradient components
|
||||
#include <GradientSignal/Components/ConstantGradientComponent.h>
|
||||
#include <GradientSignal/Components/ImageGradientComponent.h>
|
||||
#include <GradientSignal/Components/PerlinGradientComponent.h>
|
||||
#include <GradientSignal/Components/RandomGradientComponent.h>
|
||||
#include <GradientSignal/Components/ShapeAreaFalloffGradientComponent.h>
|
||||
|
||||
// Gradient modifier components
|
||||
#include <GradientSignal/Components/DitherGradientComponent.h>
|
||||
#include <GradientSignal/Components/InvertGradientComponent.h>
|
||||
#include <GradientSignal/Components/LevelsGradientComponent.h>
|
||||
#include <GradientSignal/Components/MixedGradientComponent.h>
|
||||
#include <GradientSignal/Components/PosterizeGradientComponent.h>
|
||||
#include <GradientSignal/Components/ReferenceGradientComponent.h>
|
||||
#include <GradientSignal/Components/SmoothStepGradientComponent.h>
|
||||
#include <GradientSignal/Components/ThresholdGradientComponent.h>
|
||||
|
||||
// Gradient surface data components
|
||||
#include <GradientSignal/Components/SurfaceAltitudeGradientComponent.h>
|
||||
#include <GradientSignal/Components/SurfaceMaskGradientComponent.h>
|
||||
#include <GradientSignal/Components/SurfaceSlopeGradientComponent.h>
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
@@ -32,12 +52,18 @@ namespace UnitTest
|
||||
AZ::Data::AssetManager::Create(desc);
|
||||
m_mockHandler = new ImageAssetMockAssetHandler();
|
||||
AZ::Data::AssetManager::Instance().RegisterHandler(m_mockHandler, azrtti_typeid<GradientSignal::ImageAsset>());
|
||||
|
||||
m_mockShapeHandlers = new AZStd::vector<AZStd::unique_ptr<testing::NiceMock<UnitTest::MockShapeComponentRequests>>>();
|
||||
}
|
||||
|
||||
void GradientSignalBaseFixture::TearDownCoreSystems()
|
||||
{
|
||||
// Clear any mock shape handlers that we've created for our test entities.
|
||||
delete m_mockShapeHandlers;
|
||||
|
||||
AZ::Data::AssetManager::Instance().UnregisterHandler(m_mockHandler);
|
||||
delete m_mockHandler; // delete after removing from the asset manager
|
||||
|
||||
AzFramework::LegacyAssetEventBus::ClearQueuedEvents();
|
||||
AZ::Data::AssetManager::Destroy();
|
||||
AZ::AllocatorInstance<AZ::ThreadPoolAllocator>::Destroy();
|
||||
@@ -47,6 +73,338 @@ namespace UnitTest
|
||||
m_systemEntity = nullptr;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<testing::NiceMock<UnitTest::MockShapeComponentRequests>> GradientSignalBaseFixture::CreateMockShape(
|
||||
const AZ::Aabb& spawnerBox, const AZ::EntityId& shapeEntityId)
|
||||
{
|
||||
AZStd::unique_ptr<testing::NiceMock<UnitTest::MockShapeComponentRequests>> mockShape =
|
||||
AZStd::make_unique<testing::NiceMock<UnitTest::MockShapeComponentRequests>>(shapeEntityId);
|
||||
|
||||
ON_CALL(*mockShape, GetEncompassingAabb).WillByDefault(testing::Return(spawnerBox));
|
||||
ON_CALL(*mockShape, GetTransformAndLocalBounds)
|
||||
.WillByDefault(
|
||||
[spawnerBox](AZ::Transform& transform, AZ::Aabb& bounds)
|
||||
{
|
||||
transform = AZ::Transform::CreateTranslation(spawnerBox.GetCenter());
|
||||
bounds = spawnerBox.GetTranslated(-spawnerBox.GetCenter());
|
||||
});
|
||||
ON_CALL(*mockShape, IsPointInside)
|
||||
.WillByDefault(
|
||||
[spawnerBox](const AZ::Vector3& point) -> bool
|
||||
{
|
||||
return spawnerBox.Contains(point);
|
||||
});
|
||||
|
||||
return mockShape;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<MockSurfaceDataSystem> GradientSignalBaseFixture::CreateMockSurfaceDataSystem(const AZ::Aabb& spawnerBox)
|
||||
{
|
||||
SurfaceData::SurfacePoint point;
|
||||
AZStd::unique_ptr<MockSurfaceDataSystem> mockSurfaceDataSystem = AZStd::make_unique<MockSurfaceDataSystem>();
|
||||
|
||||
// Give the mock surface data a bunch of fake point values to return.
|
||||
for (float y = spawnerBox.GetMin().GetY(); y < spawnerBox.GetMax().GetY(); y+= 1.0f)
|
||||
{
|
||||
for (float x = spawnerBox.GetMin().GetX(); x < spawnerBox.GetMax().GetX(); x += 1.0f)
|
||||
{
|
||||
// Use our x distance into the spawnerBox as an arbitrary percentage value that we'll use to calculate
|
||||
// our other arbitrary values below.
|
||||
float arbitraryPercentage = AZStd::abs(x / spawnerBox.GetExtents().GetX());
|
||||
|
||||
// Create a position that's between min and max Z of the box.
|
||||
point.m_position = AZ::Vector3(x, y, AZ::Lerp(spawnerBox.GetMin().GetZ(), spawnerBox.GetMax().GetZ(), arbitraryPercentage));
|
||||
// Create an arbitrary normal value.
|
||||
point.m_normal = point.m_position.GetNormalized();
|
||||
// Create an arbitrary surface value.
|
||||
point.m_masks[AZ_CRC_CE("test_mask")] = arbitraryPercentage;
|
||||
|
||||
mockSurfaceDataSystem->m_GetSurfacePoints[AZStd::make_pair(x, y)] = { { point } };
|
||||
}
|
||||
}
|
||||
|
||||
return mockSurfaceDataSystem;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AZ::Entity> GradientSignalBaseFixture::CreateTestEntity(float shapeHalfBounds)
|
||||
{
|
||||
// Create the base entity
|
||||
AZStd::unique_ptr<AZ::Entity> testEntity = CreateEntity();
|
||||
|
||||
// Create a mock Shape component that describes the bounds that we're using to map our gradient into world space.
|
||||
CreateComponent<MockShapeComponent>(testEntity.get());
|
||||
|
||||
// Create and keep a reference to a mock shape handler that will respond to shape requests for the mock shape.
|
||||
auto mockShapeHandler =
|
||||
CreateMockShape(AZ::Aabb::CreateCenterRadius(AZ::Vector3(shapeHalfBounds), shapeHalfBounds), testEntity->GetId());
|
||||
m_mockShapeHandlers->push_back(AZStd::move(mockShapeHandler));
|
||||
|
||||
// Create a transform that locates our gradient in the center of our desired mock Shape.
|
||||
auto transform = CreateComponent<AzFramework::TransformComponent>(testEntity.get());
|
||||
transform->SetLocalTM(AZ::Transform::CreateTranslation(AZ::Vector3(shapeHalfBounds)));
|
||||
transform->SetWorldTM(AZ::Transform::CreateTranslation(AZ::Vector3(shapeHalfBounds)));
|
||||
|
||||
return testEntity;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AZ::Entity> GradientSignalBaseFixture::BuildTestConstantGradient(float shapeHalfBounds)
|
||||
{
|
||||
// Create a Constant Gradient Component with arbitrary parameters.
|
||||
auto entity = CreateTestEntity(shapeHalfBounds);
|
||||
GradientSignal::ConstantGradientConfig config;
|
||||
config.m_value = 0.75f;
|
||||
CreateComponent<GradientSignal::ConstantGradientComponent>(entity.get(), config);
|
||||
|
||||
ActivateEntity(entity.get());
|
||||
return entity;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AZ::Entity> GradientSignalBaseFixture::BuildTestImageGradient(float shapeHalfBounds)
|
||||
{
|
||||
// Create an Image Gradient Component with arbitrary sizes and parameters.
|
||||
auto entity = CreateTestEntity(shapeHalfBounds);
|
||||
GradientSignal::ImageGradientConfig config;
|
||||
const uint32_t imageSize = 4096;
|
||||
const int32_t imageSeed = 12345;
|
||||
config.m_imageAsset = ImageAssetMockAssetHandler::CreateImageAsset(imageSize, imageSize, imageSeed);
|
||||
config.m_tilingX = 1.0f;
|
||||
config.m_tilingY = 1.0f;
|
||||
CreateComponent<GradientSignal::ImageGradientComponent>(entity.get(), config);
|
||||
|
||||
// Create a Gradient Transform Component with arbitrary parameters.
|
||||
GradientSignal::GradientTransformConfig gradientTransformConfig;
|
||||
gradientTransformConfig.m_wrappingType = GradientSignal::WrappingType::None;
|
||||
CreateComponent<GradientSignal::GradientTransformComponent>(entity.get(), gradientTransformConfig);
|
||||
|
||||
ActivateEntity(entity.get());
|
||||
return entity;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AZ::Entity> GradientSignalBaseFixture::BuildTestPerlinGradient(float shapeHalfBounds)
|
||||
{
|
||||
// Create a Perlin Gradient Component with arbitrary parameters.
|
||||
auto entity = CreateTestEntity(shapeHalfBounds);
|
||||
GradientSignal::PerlinGradientConfig config;
|
||||
config.m_amplitude = 1.0f;
|
||||
config.m_frequency = 1.1f;
|
||||
config.m_octave = 4;
|
||||
config.m_randomSeed = 12345;
|
||||
CreateComponent<GradientSignal::PerlinGradientComponent>(entity.get(), config);
|
||||
|
||||
// Create a Gradient Transform Component with arbitrary parameters.
|
||||
GradientSignal::GradientTransformConfig gradientTransformConfig;
|
||||
gradientTransformConfig.m_wrappingType = GradientSignal::WrappingType::None;
|
||||
CreateComponent<GradientSignal::GradientTransformComponent>(entity.get(), gradientTransformConfig);
|
||||
|
||||
ActivateEntity(entity.get());
|
||||
return entity;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AZ::Entity> GradientSignalBaseFixture::BuildTestRandomGradient(float shapeHalfBounds)
|
||||
{
|
||||
// Create a Random Gradient Component with arbitrary parameters.
|
||||
auto entity = CreateTestEntity(shapeHalfBounds);
|
||||
GradientSignal::RandomGradientConfig config;
|
||||
config.m_randomSeed = 12345;
|
||||
CreateComponent<GradientSignal::RandomGradientComponent>(entity.get(), config);
|
||||
|
||||
// Create a Gradient Transform Component with arbitrary parameters.
|
||||
GradientSignal::GradientTransformConfig gradientTransformConfig;
|
||||
gradientTransformConfig.m_wrappingType = GradientSignal::WrappingType::None;
|
||||
CreateComponent<GradientSignal::GradientTransformComponent>(entity.get(), gradientTransformConfig);
|
||||
|
||||
ActivateEntity(entity.get());
|
||||
return entity;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AZ::Entity> GradientSignalBaseFixture::BuildTestShapeAreaFalloffGradient(float shapeHalfBounds)
|
||||
{
|
||||
// Create a Shape Area Falloff Gradient Component with arbitrary parameters.
|
||||
auto entity = CreateTestEntity(shapeHalfBounds);
|
||||
GradientSignal::ShapeAreaFalloffGradientConfig config;
|
||||
config.m_shapeEntityId = entity->GetId();
|
||||
config.m_falloffWidth = 16.0f;
|
||||
config.m_falloffType = GradientSignal::FalloffType::InnerOuter;
|
||||
CreateComponent<GradientSignal::ShapeAreaFalloffGradientComponent>(entity.get(), config);
|
||||
|
||||
ActivateEntity(entity.get());
|
||||
return entity;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AZ::Entity> GradientSignalBaseFixture::BuildTestDitherGradient(
|
||||
float shapeHalfBounds, const AZ::EntityId& inputGradientId)
|
||||
{
|
||||
// Create a Dither Gradient Component with arbitrary parameters.
|
||||
auto entity = CreateTestEntity(shapeHalfBounds);
|
||||
GradientSignal::DitherGradientConfig config;
|
||||
config.m_gradientSampler.m_gradientId = inputGradientId;
|
||||
config.m_useSystemPointsPerUnit = false;
|
||||
config.m_pointsPerUnit = 1.0f;
|
||||
config.m_patternOffset = AZ::Vector3::CreateZero();
|
||||
config.m_patternType = GradientSignal::DitherGradientConfig::BayerPatternType::PATTERN_SIZE_4x4;
|
||||
CreateComponent<GradientSignal::DitherGradientComponent>(entity.get(), config);
|
||||
|
||||
ActivateEntity(entity.get());
|
||||
return entity;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AZ::Entity> GradientSignalBaseFixture::BuildTestInvertGradient(
|
||||
float shapeHalfBounds, const AZ::EntityId& inputGradientId)
|
||||
{
|
||||
// Create an Invert Gradient Component.
|
||||
auto entity = CreateTestEntity(shapeHalfBounds);
|
||||
GradientSignal::InvertGradientConfig config;
|
||||
config.m_gradientSampler.m_gradientId = inputGradientId;
|
||||
CreateComponent<GradientSignal::InvertGradientComponent>(entity.get(), config);
|
||||
|
||||
ActivateEntity(entity.get());
|
||||
return entity;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AZ::Entity> GradientSignalBaseFixture::BuildTestLevelsGradient(
|
||||
float shapeHalfBounds, const AZ::EntityId& inputGradientId)
|
||||
{
|
||||
// Create a Levels Gradient Component with arbitrary parameters.
|
||||
auto entity = CreateTestEntity(shapeHalfBounds);
|
||||
GradientSignal::LevelsGradientConfig config;
|
||||
config.m_gradientSampler.m_gradientId = inputGradientId;
|
||||
config.m_inputMin = 0.1f;
|
||||
config.m_inputMid = 0.3f;
|
||||
config.m_inputMax = 0.9f;
|
||||
config.m_outputMin = 0.0f;
|
||||
config.m_outputMax = 1.0f;
|
||||
CreateComponent<GradientSignal::LevelsGradientComponent>(entity.get(), config);
|
||||
|
||||
ActivateEntity(entity.get());
|
||||
return entity;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AZ::Entity> GradientSignalBaseFixture::BuildTestMixedGradient(
|
||||
float shapeHalfBounds, const AZ::EntityId& baseGradientId, const AZ::EntityId& mixedGradientId)
|
||||
{
|
||||
// Create a Mixed Gradient Component that mixes two input gradients together in arbitrary ways.
|
||||
auto entity = CreateTestEntity(shapeHalfBounds);
|
||||
GradientSignal::MixedGradientConfig config;
|
||||
|
||||
GradientSignal::MixedGradientLayer layer;
|
||||
layer.m_enabled = true;
|
||||
|
||||
layer.m_operation = GradientSignal::MixedGradientLayer::MixingOperation::Initialize;
|
||||
layer.m_gradientSampler.m_gradientId = baseGradientId;
|
||||
layer.m_gradientSampler.m_opacity = 1.0f;
|
||||
config.m_layers.push_back(layer);
|
||||
|
||||
layer.m_operation = GradientSignal::MixedGradientLayer::MixingOperation::Overlay;
|
||||
layer.m_gradientSampler.m_gradientId = mixedGradientId;
|
||||
layer.m_gradientSampler.m_opacity = 0.75f;
|
||||
config.m_layers.push_back(layer);
|
||||
|
||||
CreateComponent<GradientSignal::MixedGradientComponent>(entity.get(), config);
|
||||
|
||||
ActivateEntity(entity.get());
|
||||
return entity;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AZ::Entity> GradientSignalBaseFixture::BuildTestPosterizeGradient(
|
||||
float shapeHalfBounds, const AZ::EntityId& inputGradientId)
|
||||
{
|
||||
// Create a Posterize Gradient Component with arbitrary parameters.
|
||||
auto entity = CreateTestEntity(shapeHalfBounds);
|
||||
GradientSignal::PosterizeGradientConfig config;
|
||||
config.m_gradientSampler.m_gradientId = inputGradientId;
|
||||
config.m_mode = GradientSignal::PosterizeGradientConfig::ModeType::Ps;
|
||||
config.m_bands = 5;
|
||||
CreateComponent<GradientSignal::PosterizeGradientComponent>(entity.get(), config);
|
||||
|
||||
ActivateEntity(entity.get());
|
||||
return entity;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AZ::Entity> GradientSignalBaseFixture::BuildTestReferenceGradient(
|
||||
float shapeHalfBounds, const AZ::EntityId& inputGradientId)
|
||||
{
|
||||
// Create a Reference Gradient Component.
|
||||
auto entity = CreateTestEntity(shapeHalfBounds);
|
||||
GradientSignal::ReferenceGradientConfig config;
|
||||
config.m_gradientSampler.m_gradientId = inputGradientId;
|
||||
config.m_gradientSampler.m_ownerEntityId = entity->GetId();
|
||||
CreateComponent<GradientSignal::ReferenceGradientComponent>(entity.get(), config);
|
||||
|
||||
ActivateEntity(entity.get());
|
||||
return entity;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AZ::Entity> GradientSignalBaseFixture::BuildTestSmoothStepGradient(
|
||||
float shapeHalfBounds, const AZ::EntityId& inputGradientId)
|
||||
{
|
||||
// Create a Smooth Step Gradient Component with arbitrary parameters.
|
||||
auto entity = CreateTestEntity(shapeHalfBounds);
|
||||
GradientSignal::SmoothStepGradientConfig config;
|
||||
config.m_gradientSampler.m_gradientId = inputGradientId;
|
||||
config.m_smoothStep.m_falloffMidpoint = 0.75f;
|
||||
config.m_smoothStep.m_falloffRange = 0.125f;
|
||||
config.m_smoothStep.m_falloffStrength = 0.25f;
|
||||
CreateComponent<GradientSignal::SmoothStepGradientComponent>(entity.get(), config);
|
||||
|
||||
ActivateEntity(entity.get());
|
||||
return entity;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AZ::Entity> GradientSignalBaseFixture::BuildTestThresholdGradient(
|
||||
float shapeHalfBounds, const AZ::EntityId& inputGradientId)
|
||||
{
|
||||
// Create a Threshold Gradient Component with arbitrary parameters.
|
||||
auto entity = CreateTestEntity(shapeHalfBounds);
|
||||
GradientSignal::ThresholdGradientConfig config;
|
||||
config.m_gradientSampler.m_gradientId = inputGradientId;
|
||||
config.m_threshold = 0.75f;
|
||||
CreateComponent<GradientSignal::ThresholdGradientComponent>(entity.get(), config);
|
||||
|
||||
ActivateEntity(entity.get());
|
||||
return entity;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AZ::Entity> GradientSignalBaseFixture::BuildTestSurfaceAltitudeGradient(float shapeHalfBounds)
|
||||
{
|
||||
// Create a Surface Altitude Gradient Component with arbitrary parameters.
|
||||
auto entity = CreateTestEntity(shapeHalfBounds);
|
||||
GradientSignal::SurfaceAltitudeGradientConfig config;
|
||||
config.m_altitudeMin = -5.0f;
|
||||
config.m_altitudeMax = 15.0f;
|
||||
CreateComponent<GradientSignal::SurfaceAltitudeGradientComponent>(entity.get(), config);
|
||||
|
||||
ActivateEntity(entity.get());
|
||||
return entity;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AZ::Entity> GradientSignalBaseFixture::BuildTestSurfaceMaskGradient(float shapeHalfBounds)
|
||||
{
|
||||
// Create a Surface Mask Gradient Component with arbitrary parameters.
|
||||
auto entity = CreateTestEntity(shapeHalfBounds);
|
||||
GradientSignal::SurfaceMaskGradientConfig config;
|
||||
config.m_surfaceTagList.push_back(AZ_CRC_CE("test_mask"));
|
||||
CreateComponent<GradientSignal::SurfaceMaskGradientComponent>(entity.get(), config);
|
||||
|
||||
ActivateEntity(entity.get());
|
||||
return entity;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AZ::Entity> GradientSignalBaseFixture::BuildTestSurfaceSlopeGradient(float shapeHalfBounds)
|
||||
{
|
||||
// Create a Surface Slope Gradient Component with arbitrary parameters.
|
||||
auto entity = CreateTestEntity(shapeHalfBounds);
|
||||
GradientSignal::SurfaceSlopeGradientConfig config;
|
||||
config.m_slopeMin = 5.0f;
|
||||
config.m_slopeMax = 50.0f;
|
||||
config.m_rampType = GradientSignal::SurfaceSlopeGradientConfig::RampType::SMOOTH_STEP;
|
||||
config.m_smoothStep.m_falloffMidpoint = 0.75f;
|
||||
config.m_smoothStep.m_falloffRange = 0.125f;
|
||||
config.m_smoothStep.m_falloffStrength = 0.25f;
|
||||
CreateComponent<GradientSignal::SurfaceSlopeGradientComponent>(entity.get(), config);
|
||||
|
||||
ActivateEntity(entity.get());
|
||||
return entity;
|
||||
}
|
||||
|
||||
void GradientSignalTest::TestFixedDataSampler(const AZStd::vector<float>& expectedOutput, int size, AZ::EntityId gradientEntityId)
|
||||
{
|
||||
GradientSignal::GradientSampler gradientSampler;
|
||||
@@ -67,209 +425,5 @@ namespace UnitTest
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_BENCHMARK
|
||||
void GradientSignalBenchmarkFixture::CreateTestEntity(float shapeHalfBounds)
|
||||
{
|
||||
// Create the base entity
|
||||
m_testEntity = CreateEntity();
|
||||
|
||||
// Create a mock Shape component that describes the bounds that we're using to map our gradient into world space.
|
||||
CreateComponent<MockShapeComponent>(m_testEntity.get());
|
||||
MockShapeComponentHandler mockShapeHandler(m_testEntity->GetId());
|
||||
mockShapeHandler.m_GetLocalBounds = AZ::Aabb::CreateCenterRadius(AZ::Vector3(shapeHalfBounds), shapeHalfBounds);
|
||||
|
||||
// Create a mock Transform component that locates our gradient in the center of our desired mock Shape.
|
||||
MockTransformHandler mockTransformHandler;
|
||||
mockTransformHandler.m_GetLocalTMOutput = AZ::Transform::CreateTranslation(AZ::Vector3(shapeHalfBounds));
|
||||
mockTransformHandler.m_GetWorldTMOutput = AZ::Transform::CreateTranslation(AZ::Vector3(shapeHalfBounds));
|
||||
mockTransformHandler.BusConnect(m_testEntity->GetId());
|
||||
}
|
||||
|
||||
void GradientSignalBenchmarkFixture::DestroyTestEntity()
|
||||
{
|
||||
m_testEntity.reset();
|
||||
}
|
||||
|
||||
void GradientSignalBenchmarkFixture::CreateTestImageGradient(AZ::Entity* entity)
|
||||
{
|
||||
// Create the Image Gradient Component with some default sizes and parameters.
|
||||
GradientSignal::ImageGradientConfig config;
|
||||
const uint32_t imageSize = 4096;
|
||||
const int32_t imageSeed = 12345;
|
||||
config.m_imageAsset = ImageAssetMockAssetHandler::CreateImageAsset(imageSize, imageSize, imageSeed);
|
||||
config.m_tilingX = 1.0f;
|
||||
config.m_tilingY = 1.0f;
|
||||
CreateComponent<GradientSignal::ImageGradientComponent>(entity, config);
|
||||
|
||||
// Create the Gradient Transform Component with some default parameters.
|
||||
GradientSignal::GradientTransformConfig gradientTransformConfig;
|
||||
gradientTransformConfig.m_wrappingType = GradientSignal::WrappingType::None;
|
||||
CreateComponent<GradientSignal::GradientTransformComponent>(entity, gradientTransformConfig);
|
||||
}
|
||||
|
||||
void GradientSignalBenchmarkFixture::CreateTestPerlinGradient(AZ::Entity* entity)
|
||||
{
|
||||
// Create the Perlin Gradient Component with some default sizes and parameters.
|
||||
GradientSignal::PerlinGradientConfig config;
|
||||
config.m_amplitude = 1.0f;
|
||||
config.m_frequency = 1.1f;
|
||||
config.m_octave = 4;
|
||||
config.m_randomSeed = 12345;
|
||||
CreateComponent<GradientSignal::PerlinGradientComponent>(entity, config);
|
||||
|
||||
// Create the Gradient Transform Component with some default parameters.
|
||||
GradientSignal::GradientTransformConfig gradientTransformConfig;
|
||||
gradientTransformConfig.m_wrappingType = GradientSignal::WrappingType::None;
|
||||
CreateComponent<GradientSignal::GradientTransformComponent>(entity, gradientTransformConfig);
|
||||
}
|
||||
|
||||
void GradientSignalBenchmarkFixture::CreateTestRandomGradient(AZ::Entity* entity)
|
||||
{
|
||||
// Create the Random Gradient Component with some default parameters.
|
||||
GradientSignal::RandomGradientConfig config;
|
||||
config.m_randomSeed = 12345;
|
||||
CreateComponent<GradientSignal::RandomGradientComponent>(entity, config);
|
||||
|
||||
// Create the Gradient Transform Component with some default parameters.
|
||||
GradientSignal::GradientTransformConfig gradientTransformConfig;
|
||||
gradientTransformConfig.m_wrappingType = GradientSignal::WrappingType::None;
|
||||
CreateComponent<GradientSignal::GradientTransformComponent>(entity, gradientTransformConfig);
|
||||
}
|
||||
|
||||
void GradientSignalBenchmarkFixture::RunSamplerGetValueBenchmark(benchmark::State& state)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(Entity);
|
||||
|
||||
// All components are created, so activate the entity
|
||||
ActivateEntity(m_testEntity.get());
|
||||
|
||||
// Create a gradient sampler and run through a series of points to see if they match expectations.
|
||||
GradientSignal::GradientSampler gradientSampler;
|
||||
gradientSampler.m_gradientId = m_testEntity->GetId();
|
||||
|
||||
// Get the height and width ranges for querying from our benchmark parameters
|
||||
float height = aznumeric_cast<float>(state.range(0));
|
||||
float width = aznumeric_cast<float>(state.range(1));
|
||||
|
||||
// Call GetValue() for every height and width in our ranges.
|
||||
for (auto _ : state)
|
||||
{
|
||||
for (float y = 0.0f; y < height; y += 1.0f)
|
||||
{
|
||||
for (float x = 0.0f; x < width; x += 1.0f)
|
||||
{
|
||||
GradientSignal::GradientSampleParams params;
|
||||
params.m_position = AZ::Vector3(x, y, 0.0f);
|
||||
float value = gradientSampler.GetValue(params);
|
||||
benchmark::DoNotOptimize(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GradientSignalBenchmarkFixture::RunSamplerGetValuesBenchmark(benchmark::State& state)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(Entity);
|
||||
|
||||
// All components are created, so activate the entity
|
||||
ActivateEntity(m_testEntity.get());
|
||||
|
||||
// Create a gradient sampler and run through a series of points to see if they match expectations.
|
||||
GradientSignal::GradientSampler gradientSampler;
|
||||
gradientSampler.m_gradientId = m_testEntity->GetId();
|
||||
|
||||
// Get the height and width ranges for querying from our benchmark parameters
|
||||
float height = aznumeric_cast<float>(state.range(0));
|
||||
float width = aznumeric_cast<float>(state.range(1));
|
||||
int64_t totalQueryPoints = state.range(0) * state.range(1);
|
||||
|
||||
// Call GetValues() for every height and width in our ranges.
|
||||
for (auto _ : state)
|
||||
{
|
||||
// Set up our vector of query positions.
|
||||
AZStd::vector<AZ::Vector3> positions(totalQueryPoints);
|
||||
size_t index = 0;
|
||||
for (float y = 0.0f; y < height; y += 1.0f)
|
||||
{
|
||||
for (float x = 0.0f; x < width; x += 1.0f)
|
||||
{
|
||||
positions[index++] = AZ::Vector3(x, y, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
// Query and get the results.
|
||||
AZStd::vector<float> results(totalQueryPoints);
|
||||
gradientSampler.GetValues(positions, results);
|
||||
}
|
||||
}
|
||||
|
||||
void GradientSignalBenchmarkFixture::RunEBusGetValueBenchmark(benchmark::State& state)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(Entity);
|
||||
|
||||
// All components are created, so activate the entity
|
||||
ActivateEntity(m_testEntity.get());
|
||||
|
||||
GradientSignal::GradientSampleParams params;
|
||||
|
||||
// Get the height and width ranges for querying from our benchmark parameters
|
||||
float height = aznumeric_cast<float>(state.range(0));
|
||||
float width = aznumeric_cast<float>(state.range(1));
|
||||
|
||||
// Call GetValue() for every height and width in our ranges.
|
||||
for (auto _ : state)
|
||||
{
|
||||
for (float y = 0.0f; y < height; y += 1.0f)
|
||||
{
|
||||
for (float x = 0.0f; x < width; x += 1.0f)
|
||||
{
|
||||
float value = 0.0f;
|
||||
params.m_position = AZ::Vector3(x, y, 0.0f);
|
||||
GradientSignal::GradientRequestBus::EventResult(
|
||||
value, m_testEntity->GetId(), &GradientSignal::GradientRequestBus::Events::GetValue, params);
|
||||
benchmark::DoNotOptimize(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GradientSignalBenchmarkFixture::RunEBusGetValuesBenchmark(benchmark::State& state)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(Entity);
|
||||
|
||||
// All components are created, so activate the entity
|
||||
ActivateEntity(m_testEntity.get());
|
||||
|
||||
GradientSignal::GradientSampler gradientSampler;
|
||||
gradientSampler.m_gradientId = m_testEntity->GetId();
|
||||
|
||||
// Get the height and width ranges for querying from our benchmark parameters
|
||||
float height = aznumeric_cast<float>(state.range(0));
|
||||
float width = aznumeric_cast<float>(state.range(1));
|
||||
int64_t totalQueryPoints = state.range(0) * state.range(1);
|
||||
|
||||
// Call GetValues() for every height and width in our ranges.
|
||||
for (auto _ : state)
|
||||
{
|
||||
// Set up our vector of query positions.
|
||||
AZStd::vector<AZ::Vector3> positions(totalQueryPoints);
|
||||
size_t index = 0;
|
||||
for (float y = 0.0f; y < height; y += 1.0f)
|
||||
{
|
||||
for (float x = 0.0f; x < width; x += 1.0f)
|
||||
{
|
||||
positions[index++] = AZ::Vector3(x, y, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
// Query and get the results.
|
||||
AZStd::vector<float> results(totalQueryPoints);
|
||||
GradientSignal::GradientRequestBus::Event(
|
||||
m_testEntity->GetId(), &GradientSignal::GradientRequestBus::Events::GetValues, positions, results);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <Tests/GradientSignalTestMocks.h>
|
||||
#include <LmbrCentral/Shape/MockShapes.h>
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
@@ -30,22 +31,56 @@ namespace UnitTest
|
||||
}
|
||||
|
||||
template<typename Component, typename Configuration>
|
||||
AZ::Component* CreateComponent(AZ::Entity* entity, const Configuration& config)
|
||||
Component* CreateComponent(AZ::Entity* entity, const Configuration& config)
|
||||
{
|
||||
m_app->RegisterComponentDescriptor(Component::CreateDescriptor());
|
||||
return entity->CreateComponent<Component>(config);
|
||||
}
|
||||
|
||||
template<typename Component>
|
||||
AZ::Component* CreateComponent(AZ::Entity* entity)
|
||||
Component* CreateComponent(AZ::Entity* entity)
|
||||
{
|
||||
m_app->RegisterComponentDescriptor(Component::CreateDescriptor());
|
||||
return entity->CreateComponent<Component>();
|
||||
}
|
||||
|
||||
// Create a mock shape that will respond to the shape bus with proper responses for the given input box.
|
||||
AZStd::unique_ptr<testing::NiceMock<UnitTest::MockShapeComponentRequests>> CreateMockShape(
|
||||
const AZ::Aabb& spawnerBox, const AZ::EntityId& shapeEntityId);
|
||||
|
||||
// Create a mock SurfaceDataSystem that will respond to requests for surface points with mock responses for points inside
|
||||
// the given input box.
|
||||
AZStd::unique_ptr<MockSurfaceDataSystem> CreateMockSurfaceDataSystem(const AZ::Aabb& spawnerBox);
|
||||
|
||||
// Create an entity with a mock shape and a transform. It won't be activated yet though, because we expect a gradient component
|
||||
// to also get added to it first before activation.
|
||||
AZStd::unique_ptr<AZ::Entity> CreateTestEntity(float shapeHalfBounds);
|
||||
|
||||
// Create and activate an entity with a gradient component of the requested type, initialized with test data.
|
||||
AZStd::unique_ptr<AZ::Entity> BuildTestConstantGradient(float shapeHalfBounds);
|
||||
AZStd::unique_ptr<AZ::Entity> BuildTestImageGradient(float shapeHalfBounds);
|
||||
AZStd::unique_ptr<AZ::Entity> BuildTestPerlinGradient(float shapeHalfBounds);
|
||||
AZStd::unique_ptr<AZ::Entity> BuildTestRandomGradient(float shapeHalfBounds);
|
||||
AZStd::unique_ptr<AZ::Entity> BuildTestShapeAreaFalloffGradient(float shapeHalfBounds);
|
||||
|
||||
AZStd::unique_ptr<AZ::Entity> BuildTestDitherGradient(float shapeHalfBounds, const AZ::EntityId& inputGradientId);
|
||||
AZStd::unique_ptr<AZ::Entity> BuildTestInvertGradient(float shapeHalfBounds, const AZ::EntityId& inputGradientId);
|
||||
AZStd::unique_ptr<AZ::Entity> BuildTestLevelsGradient(float shapeHalfBounds, const AZ::EntityId& inputGradientId);
|
||||
AZStd::unique_ptr<AZ::Entity> BuildTestMixedGradient(
|
||||
float shapeHalfBounds, const AZ::EntityId& baseGradientId, const AZ::EntityId& mixedGradientId);
|
||||
AZStd::unique_ptr<AZ::Entity> BuildTestPosterizeGradient(float shapeHalfBounds, const AZ::EntityId& inputGradientId);
|
||||
AZStd::unique_ptr<AZ::Entity> BuildTestReferenceGradient(float shapeHalfBounds, const AZ::EntityId& inputGradientId);
|
||||
AZStd::unique_ptr<AZ::Entity> BuildTestSmoothStepGradient(float shapeHalfBounds, const AZ::EntityId& inputGradientId);
|
||||
AZStd::unique_ptr<AZ::Entity> BuildTestThresholdGradient(float shapeHalfBounds, const AZ::EntityId& inputGradientId);
|
||||
|
||||
AZStd::unique_ptr<AZ::Entity> BuildTestSurfaceAltitudeGradient(float shapeHalfBounds);
|
||||
AZStd::unique_ptr<AZ::Entity> BuildTestSurfaceMaskGradient(float shapeHalfBounds);
|
||||
AZStd::unique_ptr<AZ::Entity> BuildTestSurfaceSlopeGradient(float shapeHalfBounds);
|
||||
|
||||
AZStd::unique_ptr<AZ::ComponentApplication> m_app;
|
||||
AZ::Entity* m_systemEntity = nullptr;
|
||||
ImageAssetMockAssetHandler* m_mockHandler = nullptr;
|
||||
AZStd::vector<AZStd::unique_ptr<testing::NiceMock<UnitTest::MockShapeComponentRequests>>>* m_mockShapeHandlers = nullptr;
|
||||
};
|
||||
|
||||
struct GradientSignalTest
|
||||
@@ -80,33 +115,15 @@ namespace UnitTest
|
||||
AZ::Debug::TraceMessageBus::Handler::BusConnect();
|
||||
UnitTest::AllocatorsBenchmarkFixture::SetUp(state);
|
||||
SetupCoreSystems();
|
||||
|
||||
// Create a default test entity with bounds of 256 m x 256 m x 256 m.
|
||||
const float shapeHalfBounds = 128.0f;
|
||||
CreateTestEntity(shapeHalfBounds);
|
||||
}
|
||||
|
||||
void internalTearDown(const benchmark::State& state)
|
||||
{
|
||||
DestroyTestEntity();
|
||||
TearDownCoreSystems();
|
||||
UnitTest::AllocatorsBenchmarkFixture::TearDown(state);
|
||||
AZ::Debug::TraceMessageBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void CreateTestEntity(float shapeHalfBounds);
|
||||
void DestroyTestEntity();
|
||||
|
||||
void CreateTestImageGradient(AZ::Entity* entity);
|
||||
void CreateTestPerlinGradient(AZ::Entity* entity);
|
||||
void CreateTestRandomGradient(AZ::Entity* entity);
|
||||
|
||||
void RunSamplerGetValueBenchmark(benchmark::State& state);
|
||||
void RunSamplerGetValuesBenchmark(benchmark::State& state);
|
||||
|
||||
void RunEBusGetValueBenchmark(benchmark::State& state);
|
||||
void RunEBusGetValuesBenchmark(benchmark::State& state);
|
||||
|
||||
protected:
|
||||
void SetUp(const benchmark::State& state) override
|
||||
{
|
||||
@@ -125,8 +142,6 @@ namespace UnitTest
|
||||
{
|
||||
internalTearDown(state);
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AZ::Entity> m_testEntity;
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
set(FILES
|
||||
Tests/GradientSignalBenchmarks.cpp
|
||||
Tests/GradientSignalGetValuesTests.cpp
|
||||
Tests/GradientSignalImageTests.cpp
|
||||
Tests/GradientSignalReferencesTests.cpp
|
||||
Tests/GradientSignalServicesTests.cpp
|
||||
|
||||
@@ -190,7 +190,7 @@ namespace LmbrCentral
|
||||
{
|
||||
AZ::Crc32 result = {};
|
||||
|
||||
AZ_WarningOnce("Vegetation", !m_isRequestInProgress, "Detected cyclic dependences with vegetation entity references");
|
||||
AZ_WarningOnce("Shape", !m_isRequestInProgress, "Detected cyclic dependencies with shape entity references");
|
||||
if (AllowRequest())
|
||||
{
|
||||
m_isRequestInProgress = true;
|
||||
@@ -205,7 +205,7 @@ namespace LmbrCentral
|
||||
{
|
||||
AZ::Aabb result = AZ::Aabb::CreateNull();
|
||||
|
||||
AZ_WarningOnce("Vegetation", !m_isRequestInProgress, "Detected cyclic dependences with vegetation entity references");
|
||||
AZ_WarningOnce("Shape", !m_isRequestInProgress, "Detected cyclic dependencies with shape entity references");
|
||||
if (AllowRequest())
|
||||
{
|
||||
m_isRequestInProgress = true;
|
||||
@@ -221,7 +221,7 @@ namespace LmbrCentral
|
||||
transform = AZ::Transform::CreateIdentity();
|
||||
bounds = AZ::Aabb::CreateNull();
|
||||
|
||||
AZ_WarningOnce("Vegetation", !m_isRequestInProgress, "Detected cyclic dependences with vegetation entity references");
|
||||
AZ_WarningOnce("Shape", !m_isRequestInProgress, "Detected cyclic dependencies with shape entity references");
|
||||
if (AllowRequest())
|
||||
{
|
||||
m_isRequestInProgress = true;
|
||||
@@ -234,7 +234,7 @@ namespace LmbrCentral
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
AZ_WarningOnce("Vegetation", !m_isRequestInProgress, "Detected cyclic dependences with vegetation entity references");
|
||||
AZ_WarningOnce("Shape", !m_isRequestInProgress, "Detected cyclic dependencies with shape entity references");
|
||||
if (AllowRequest())
|
||||
{
|
||||
m_isRequestInProgress = true;
|
||||
@@ -249,7 +249,7 @@ namespace LmbrCentral
|
||||
{
|
||||
float result = FLT_MAX;
|
||||
|
||||
AZ_WarningOnce("Vegetation", !m_isRequestInProgress, "Detected cyclic dependences with vegetation entity references");
|
||||
AZ_WarningOnce("Shape", !m_isRequestInProgress, "Detected cyclic dependencies with shape entity references");
|
||||
if (AllowRequest())
|
||||
{
|
||||
m_isRequestInProgress = true;
|
||||
@@ -264,7 +264,7 @@ namespace LmbrCentral
|
||||
{
|
||||
float result = FLT_MAX;
|
||||
|
||||
AZ_WarningOnce("Vegetation", !m_isRequestInProgress, "Detected cyclic dependences with vegetation entity references");
|
||||
AZ_WarningOnce("Shape", !m_isRequestInProgress, "Detected cyclic dependencies with shape entity references");
|
||||
if (AllowRequest())
|
||||
{
|
||||
m_isRequestInProgress = true;
|
||||
@@ -279,7 +279,7 @@ namespace LmbrCentral
|
||||
{
|
||||
AZ::Vector3 result = AZ::Vector3::CreateZero();
|
||||
|
||||
AZ_WarningOnce("Vegetation", !m_isRequestInProgress, "Detected cyclic dependences with vegetation entity references");
|
||||
AZ_WarningOnce("Shape", !m_isRequestInProgress, "Detected cyclic dependencies with shape entity references");
|
||||
if (AllowRequest())
|
||||
{
|
||||
m_isRequestInProgress = true;
|
||||
@@ -294,7 +294,7 @@ namespace LmbrCentral
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
AZ_WarningOnce("Vegetation", !m_isRequestInProgress, "Detected cyclic dependences with vegetation entity references");
|
||||
AZ_WarningOnce("Shape", !m_isRequestInProgress, "Detected cyclic dependencies with shape entity references");
|
||||
if (AllowRequest())
|
||||
{
|
||||
m_isRequestInProgress = true;
|
||||
|
||||
@@ -160,7 +160,7 @@ namespace Terrain
|
||||
{
|
||||
float maxSample = 0.0f;
|
||||
terrainExists = false;
|
||||
AZ_WarningOnce("Terrain", !m_isRequestInProgress, "Detected cyclic dependences with terrain height entity references");
|
||||
AZ_WarningOnce("Terrain", !m_isRequestInProgress, "Detected cyclic dependencies with terrain height entity references");
|
||||
if (!m_isRequestInProgress)
|
||||
{
|
||||
m_isRequestInProgress = true;
|
||||
|
||||
@@ -224,7 +224,7 @@ namespace Vegetation
|
||||
|
||||
bool result = true;
|
||||
|
||||
AZ_WarningOnce("Vegetation", !m_isRequestInProgress, "Detected cyclic dependences with vegetation entity references");
|
||||
AZ_WarningOnce("Vegetation", !m_isRequestInProgress, "Detected cyclic dependencies with vegetation entity references");
|
||||
if (!m_isRequestInProgress)
|
||||
{
|
||||
m_isRequestInProgress = true;
|
||||
@@ -264,7 +264,7 @@ namespace Vegetation
|
||||
return;
|
||||
}
|
||||
|
||||
AZ_WarningOnce("Vegetation", !m_isRequestInProgress, "Detected cyclic dependences with vegetation entity references");
|
||||
AZ_WarningOnce("Vegetation", !m_isRequestInProgress, "Detected cyclic dependencies with vegetation entity references");
|
||||
if (!m_isRequestInProgress)
|
||||
{
|
||||
m_isRequestInProgress = true;
|
||||
@@ -295,7 +295,7 @@ namespace Vegetation
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(Entity);
|
||||
|
||||
AZ_WarningOnce("Vegetation", !m_isRequestInProgress, "Detected cyclic dependences with vegetation entity references");
|
||||
AZ_WarningOnce("Vegetation", !m_isRequestInProgress, "Detected cyclic dependencies with vegetation entity references");
|
||||
if (!m_isRequestInProgress)
|
||||
{
|
||||
m_isRequestInProgress = true;
|
||||
@@ -320,7 +320,7 @@ namespace Vegetation
|
||||
LmbrCentral::ShapeComponentRequestsBus::EventResult(bounds, GetEntityId(), &LmbrCentral::ShapeComponentRequestsBus::Events::GetEncompassingAabb);
|
||||
}
|
||||
|
||||
AZ_WarningOnce("Vegetation", !m_isRequestInProgress, "Detected cyclic dependences with vegetation entity references");
|
||||
AZ_WarningOnce("Vegetation", !m_isRequestInProgress, "Detected cyclic dependencies with vegetation entity references");
|
||||
if (!m_isRequestInProgress)
|
||||
{
|
||||
m_isRequestInProgress = true;
|
||||
@@ -344,7 +344,7 @@ namespace Vegetation
|
||||
|
||||
AZ::u32 count = 0;
|
||||
|
||||
AZ_WarningOnce("Vegetation", !m_isRequestInProgress, "Detected cyclic dependences with vegetation entity references");
|
||||
AZ_WarningOnce("Vegetation", !m_isRequestInProgress, "Detected cyclic dependencies with vegetation entity references");
|
||||
if (!m_isRequestInProgress)
|
||||
{
|
||||
m_isRequestInProgress = true;
|
||||
|
||||
Reference in New Issue
Block a user