GradientSignalTestHelpers.h 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #pragma once
  9. #include <AzCore/Component/EntityId.h>
  10. #include <AzCore/Math/Aabb.h>
  11. #include <AzCore/Math/Vector3.h>
  12. #include <AzCore/std/containers/vector.h>
  13. #include <AzTest/AzTest.h>
  14. #include <Atom/RHI.Reflect/ImageSubresource.h>
  15. #include <Atom/RPI.Reflect/Image/ImageMipChainAsset.h>
  16. #include <Atom/RPI.Reflect/Image/StreamingImageAsset.h>
  17. namespace UnitTest
  18. {
  19. //! Helper method to build a AZ::RHI::ImageSubresourceLayout
  20. //! @param width The width of the image
  21. //! @param height The height of the image
  22. //! @param pixelSize Number of bytes per pixel
  23. //! @return The AZ::RHI::ImageSubresourceLayout that has been filled out appropriately
  24. AZ::RHI::DeviceImageSubresourceLayout BuildSubImageLayout(AZ::u32 width, AZ::u32 height, AZ::u32 pixelSize);
  25. //! Build a deterministic random set of image pixel data
  26. //! @param width Width of the image
  27. //! @param height Height of the image
  28. //! @param pixelSize Number of bytes per pixel
  29. //! @param seed The random seed for generating the data
  30. //! @return A vector of bytes for the image data
  31. AZStd::vector<uint8_t> BuildBasicImageData(AZ::u32 width, AZ::u32 height, AZ::u32 pixelSize, AZ::s32 seed);
  32. //! Build a mip chain asset that contains the basic image data from BuildBasicImageData
  33. //! @param mipLevels Number of mip levels in the chain
  34. //! @param width The width of the image
  35. //! @param height The height of the image
  36. //! @param pixelSize The number of bytes per pixel
  37. //! @param data The raw pixel data
  38. //! @return A mip chain asset with the specified basic image data
  39. AZ::Data::Asset<AZ::RPI::ImageMipChainAsset> BuildBasicMipChainAsset(
  40. AZ::u16 mipLevels, AZ::u32 width, AZ::u32 height, AZ::u32 pixelSize, AZStd::span<const uint8_t> data);
  41. //! Construct an array of image data where all the pixels are 0 except for one at the given coordinate
  42. //! @param width Width of the image
  43. //! @param height Height of the image
  44. //! @param pixelSize Number of bytes per pixel
  45. //! @param pixelX The X coordinate of the pixel to set to a specific value
  46. //! @param pixelY The Y coordinate of the pixel to set to a specific value
  47. //! @param setPixelValues The values to set the one specific pixel to (one value per pixel channel, determined by pixelSize)
  48. //! @return A vector of bytes for the image data
  49. AZStd::vector<uint8_t> BuildSpecificPixelImageData(
  50. AZ::u32 width, AZ::u32 height, AZ::u32 pixelSize, AZ::u32 pixelX, AZ::u32 pixelY, AZStd::span<const AZ::u8> setPixelValues);
  51. //! Given a set of raw pixel data, create an AZ::RPI::StreamingImageAsset
  52. //! @param width The width of the image
  53. //! @param height The height of the image
  54. //! @param format The format of the pixel data
  55. //! @param data The raw pixel data
  56. //! \return The AZ::RPI::StreamingImageAsset in a loaded ready state
  57. AZ::Data::Asset<AZ::RPI::StreamingImageAsset> CreateImageAssetFromPixelData(
  58. AZ::u32 width, AZ::u32 height, AZ::RHI::Format format, AZStd::span<const uint8_t> data);
  59. //! Creates a deterministically random set of pixel data as an AZ::RPI::StreamingImageAsset.
  60. //! \param width The width of the AZ::RPI::StreamingImageAsset
  61. //! \param height The height of the AZ::RPI::StreamingImageAsset
  62. //! \param seed The random seed to use for generating the random data
  63. //! \return The AZ::RPI::StreamingImageAsset in a loaded ready state
  64. AZ::Data::Asset<AZ::RPI::StreamingImageAsset> CreateImageAsset(AZ::u32 width, AZ::u32 height, AZ::s32 seed);
  65. //! Creates an AZ::RPI::StreamingImageAsset where all the pixels are 0 except for the one pixel at the given coordinates, which is set to a specific value based on the component.
  66. //! \param width The width of the AZ::RPI::StreamingImageAsset
  67. //! \param height The height of the AZ::RPI::StreamingImageAsset
  68. //! \param pixelX The X coordinate of the pixel to set to a specific value
  69. //! \param pixelY The Y coordinate of the pixel to set to a specific value
  70. //! @param setPixelValues The values to set the one specific pixel to (one value per pixel channel, determined by pixelSize)
  71. //! \return The AZ::RPI::StreamingImageAsset in a loaded ready state
  72. AZ::Data::Asset<AZ::RPI::StreamingImageAsset> CreateSpecificPixelImageAsset(
  73. AZ::u32 width, AZ::u32 height, AZ::u32 pixelX, AZ::u32 pixelY, AZStd::span<const AZ::u8> setPixelValues);
  74. //! Converts a set of pixel coordinates in an image to a world space value that represents the center of the pixel.
  75. //! \param pixelX The X coordinate of the pixel to convert.
  76. //! \param pixelY The Y coordinate of the pixel to convert.
  77. //! \param bounds The world space bounds of the image.
  78. //! \param width The width of the image in pixels.
  79. //! \param height The height of the image in pixels.
  80. //! @return The world space center of the requested pixel.
  81. AZ::Vector3 PixelCoordinatesToWorldSpace(uint32_t pixelX, uint32_t pixelY, const AZ::Aabb& bounds, uint32_t width, uint32_t height);
  82. class GradientSignalTestHelpers
  83. {
  84. public:
  85. static void CompareGetValueAndGetValues(AZ::EntityId gradientEntityId, float queryMin, float queryMax);
  86. #ifdef HAVE_BENCHMARK
  87. // We use an enum to list out the different types of GetValue() benchmarks to run so that way we can condense our test cases
  88. // to just take the value in as a benchmark argument and switch on it. Otherwise, we would need to write a different benchmark
  89. // function for each test case for each gradient.
  90. enum GetValuePermutation : int64_t
  91. {
  92. EBUS_GET_VALUE,
  93. EBUS_GET_VALUES,
  94. SAMPLER_GET_VALUE,
  95. SAMPLER_GET_VALUES,
  96. };
  97. static void FillQueryPositions(AZStd::vector<AZ::Vector3>& positions, float height, float width);
  98. static void RunEBusGetValueBenchmark(benchmark::State& state, const AZ::EntityId& gradientId, int64_t queryRange);
  99. static void RunEBusGetValuesBenchmark(benchmark::State& state, const AZ::EntityId& gradientId, int64_t queryRange);
  100. static void RunSamplerGetValueBenchmark(benchmark::State& state, const AZ::EntityId& gradientId, int64_t queryRange);
  101. static void RunSamplerGetValuesBenchmark(benchmark::State& state, const AZ::EntityId& gradientId, int64_t queryRange);
  102. static void RunGetValueOrGetValuesBenchmark(benchmark::State& state, const AZ::EntityId& gradientId);
  103. // 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
  104. // registering one set of benchmark runs for each enum value and use ArgNames() to give it a friendly name in the results.
  105. #ifndef GRADIENT_SIGNAL_GET_VALUES_BENCHMARK_REGISTER_F
  106. #define GRADIENT_SIGNAL_GET_VALUES_BENCHMARK_REGISTER_F(Fixture, Func) \
  107. BENCHMARK_REGISTER_F(Fixture, Func) \
  108. ->Args({ GradientSignalTestHelpers::GetValuePermutation::EBUS_GET_VALUE, 1024 }) \
  109. ->Args({ GradientSignalTestHelpers::GetValuePermutation::EBUS_GET_VALUE, 2048 }) \
  110. ->ArgNames({ "EbusGetValue", "size" }) \
  111. ->Unit(::benchmark::kMillisecond); \
  112. BENCHMARK_REGISTER_F(Fixture, Func) \
  113. ->Args({ GradientSignalTestHelpers::GetValuePermutation::EBUS_GET_VALUES, 1024 }) \
  114. ->Args({ GradientSignalTestHelpers::GetValuePermutation::EBUS_GET_VALUES, 2048 }) \
  115. ->ArgNames({ "EbusGetValues", "size" }) \
  116. ->Unit(::benchmark::kMillisecond); \
  117. BENCHMARK_REGISTER_F(Fixture, Func) \
  118. ->Args({ GradientSignalTestHelpers::GetValuePermutation::SAMPLER_GET_VALUE, 1024 }) \
  119. ->Args({ GradientSignalTestHelpers::GetValuePermutation::SAMPLER_GET_VALUE, 2048 }) \
  120. ->ArgNames({ "SamplerGetValue", "size" }) \
  121. ->Unit(::benchmark::kMillisecond); \
  122. BENCHMARK_REGISTER_F(Fixture, Func) \
  123. ->Args({ GradientSignalTestHelpers::GetValuePermutation::SAMPLER_GET_VALUES, 1024 }) \
  124. ->Args({ GradientSignalTestHelpers::GetValuePermutation::SAMPLER_GET_VALUES, 2048 }) \
  125. ->ArgNames({ "SamplerGetValues", "size" }) \
  126. ->Unit(::benchmark::kMillisecond);
  127. #endif
  128. #endif
  129. };
  130. }