Utils.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  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. #include <Utils/Utils.h>
  9. #include <AtomCore/Instance/InstanceDatabase.h>
  10. #include <Atom/RHI/RHISystemInterface.h>
  11. #include <Atom/RPI.Public/RenderPipeline.h>
  12. #include <Atom/RPI.Public/RPISystemInterface.h>
  13. #include <Atom/RPI.Public/Scene.h>
  14. #include <Atom/RPI.Public/Image/ImageSystemInterface.h>
  15. #include <Atom/RPI.Reflect/Asset/AssetUtils.h>
  16. #include <Atom/RPI.Reflect/Image/StreamingImageAssetCreator.h>
  17. #include <Atom/RPI.Reflect/Image/ImageMipChainAssetCreator.h>
  18. #include <Atom/Utils/DdsFile.h>
  19. #ifdef AZ_PROFILE_TELEMETRY
  20. #include <RADTelemetry/ProfileTelemetryBus.h>
  21. #endif
  22. #include <AzFramework/CommandLine/CommandLine.h>
  23. #include <AzFramework/API/ApplicationAPI.h>
  24. #include <AzFramework/Windowing/NativeWindow.h>
  25. #include <AzCore/Asset/AssetCommon.h>
  26. #include <AzCore/PlatformIncl.h>
  27. #include <AzCore/IO/SystemFile.h>
  28. #include <AzCore/IO/Path/Path.h>
  29. #include <Automation/ScriptRepeaterBus.h>
  30. namespace AtomSampleViewer
  31. {
  32. namespace Utils
  33. {
  34. AZ::RHI::Ptr<AZ::RHI::Device> GetRHIDevice()
  35. {
  36. using namespace AZ;
  37. auto* rhiSystem = RHI::RHISystemInterface::Get();
  38. AZ_Assert(rhiSystem, "Failed to retrieve rpi system.");
  39. return rhiSystem->GetDevice();
  40. }
  41. bool AssetEntryNameGetter(void* data, int index, const char** outName)
  42. {
  43. const AssetEntry* assetEntries = reinterpret_cast<const AssetEntry*>(data);
  44. *outName = assetEntries[index].m_name.c_str();
  45. return true;
  46. }
  47. void ToggleRadTMCapture()
  48. {
  49. #ifdef AZ_PROFILE_TELEMETRY
  50. using namespace RADTelemetry;
  51. using MaskType = AZ::Debug::ProfileCategoryPrimitiveType;
  52. // Set all the category bits "below" Detailed by default
  53. static const MaskType defaultCaptureMask = AZ_PROFILE_CAT_TO_RAD_CAPFLAGS(FirstDetailedCategory) - 1;
  54. static const char* s_telemetryAddress = "127.0.0.1";
  55. static int32_t s_telemetryPort = 4719;
  56. static MaskType s_telemetryCaptureMask = defaultCaptureMask;
  57. static int32_t s_memCaptureEnabled = 0;
  58. ProfileTelemetryRequestBus::Broadcast(&ProfileTelemetryRequestBus::Events::SetAddress, s_telemetryAddress, s_telemetryPort);
  59. const MaskType fullCaptureMask = s_telemetryCaptureMask | (s_memCaptureEnabled ? AZ_PROFILE_CAT_TO_RAD_CAPFLAGS(MemoryReserved) : 0);
  60. ProfileTelemetryRequestBus::Broadcast(&ProfileTelemetryRequestBus::Events::SetCaptureMask, fullCaptureMask);
  61. ProfileTelemetryRequestBus::Broadcast(&ProfileTelemetryRequestBus::Events::ToggleEnabled);
  62. #endif // AZ_PROFILE_TELEMETRY
  63. }
  64. DefaultIBL::~DefaultIBL()
  65. {
  66. Reset();
  67. }
  68. void DefaultIBL::PreloadAssets()
  69. {
  70. const constexpr char* DiffuseAssetPath = "textures/sampleenvironment/examplespecularhdr_cm_ibldiffuse.dds.streamingimage";
  71. const constexpr char* SpecularAssetPath = "textures/sampleenvironment/examplespecularhdr_cm_iblspecular.dds.streamingimage";
  72. auto assertTraceLevel = AZ::RPI::AssetUtils::TraceLevel::Assert;
  73. if (!m_diffuseImageAsset.IsReady())
  74. {
  75. m_diffuseImageAsset = AZ::RPI::AssetUtils::GetAssetByProductPath<AZ::RPI::StreamingImageAsset>(DiffuseAssetPath, assertTraceLevel);
  76. m_diffuseImageAsset.QueueLoad();
  77. m_diffuseImageAsset.BlockUntilLoadComplete();
  78. }
  79. if (!m_specularImageAsset.IsReady())
  80. {
  81. m_specularImageAsset = AZ::RPI::AssetUtils::GetAssetByProductPath<AZ::RPI::StreamingImageAsset>(SpecularAssetPath, assertTraceLevel);
  82. m_specularImageAsset.QueueLoad();
  83. m_specularImageAsset.BlockUntilLoadComplete();
  84. }
  85. }
  86. void DefaultIBL::Init(AZ::RPI::Scene* scene)
  87. {
  88. PreloadAssets();
  89. m_featureProcessor = scene->GetFeatureProcessor<AZ::Render::ImageBasedLightFeatureProcessorInterface>();
  90. AZ_Assert(m_featureProcessor, "Unabled to find ImageBasedLightFeatureProcessorInterface on scene.");
  91. m_featureProcessor->SetDiffuseImage(m_diffuseImageAsset);
  92. m_featureProcessor->SetSpecularImage(m_specularImageAsset);
  93. }
  94. void DefaultIBL::SetExposure(float exposure)
  95. {
  96. m_featureProcessor->SetExposure(exposure);
  97. }
  98. void DefaultIBL::Reset()
  99. {
  100. if (m_featureProcessor)
  101. {
  102. m_featureProcessor->Reset();
  103. m_featureProcessor = nullptr;
  104. }
  105. }
  106. void ResizeClientArea(uint32_t width, uint32_t height)
  107. {
  108. AzFramework::NativeWindowHandle windowHandle = nullptr;
  109. AzFramework::WindowSystemRequestBus::BroadcastResult(
  110. windowHandle,
  111. &AzFramework::WindowSystemRequestBus::Events::GetDefaultWindowHandle);
  112. AzFramework::WindowSize clientAreaSize = {width, height};
  113. AzFramework::WindowRequestBus::Event(windowHandle, &AzFramework::WindowRequestBus::Events::ResizeClientArea, clientAreaSize);
  114. AzFramework::WindowSize newWindowSize;
  115. AzFramework::WindowRequestBus::EventResult(newWindowSize, windowHandle, &AzFramework::WindowRequests::GetClientAreaSize);
  116. AZ_Error("ResizeClientArea", newWindowSize.m_width == width && newWindowSize.m_height == height,
  117. "Requested window resize to %ux%u but got %ux%u. This display resolution is too low or desktop scaling is too high.",
  118. width, height, newWindowSize.m_width, newWindowSize.m_height);
  119. }
  120. bool SupportsToggleFullScreenOfDefaultWindow()
  121. {
  122. return AzFramework::NativeWindow::CanToggleFullScreenStateOfDefaultWindow();
  123. }
  124. void ToggleFullScreenOfDefaultWindow()
  125. {
  126. AzFramework::NativeWindow::ToggleFullScreenStateOfDefaultWindow();
  127. }
  128. void ReportScriptableAction(const char* formatStr, ...)
  129. {
  130. va_list args;
  131. va_start(args, formatStr);
  132. ScriptRepeaterRequestBus::Broadcast(&ScriptRepeaterRequests::ReportScriptableAction, AZStd::string::format_arg(formatStr, args));
  133. va_end(args);
  134. }
  135. AZ::Data::Instance<AZ::RPI::StreamingImage> GetSolidColorCubemap(uint32_t color)
  136. {
  137. constexpr uint32_t width = 4;
  138. constexpr uint32_t height = 4;
  139. AZStd::string assetName = AZStd::string::format("SolidColorBackground_%u", color);
  140. AZ::Data::AssetId assetId = AZ::Uuid::CreateName(assetName.c_str());
  141. // Check for existing image of the same color
  142. AZ::Data::Instance<AZ::RPI::StreamingImage> existingImage = AZ::Data::InstanceDatabase<AZ::RPI::StreamingImage>::Instance().Find(AZ::Data::InstanceId::CreateFromAssetId(assetId));
  143. if (existingImage)
  144. {
  145. return existingImage;
  146. }
  147. // Build a new cubemap.
  148. AZ::RHI::Size imageSize = AZ::RHI::Size(width, height, 1);
  149. const uint32_t pixelSize = sizeof(uint32_t);
  150. const uint32_t pixelDataSize = width * height * pixelSize;
  151. AZStd::array<uint32_t, width* height> pixels;
  152. for (uint32_t& pixelColor : pixels)
  153. {
  154. pixelColor = color;
  155. }
  156. // Create a new streaming image
  157. AZ::RPI::StreamingImageAssetCreator imageCreator;
  158. imageCreator.Begin(assetId);
  159. int32_t arraySize = 6;
  160. AZ::RHI::Format format = AZ::RHI::Format::R8G8B8A8_UNORM_SRGB;
  161. AZ::RHI::ImageBindFlags bindFlag = AZ::RHI::ImageBindFlags::ShaderRead;
  162. AZ::RHI::ImageDescriptor imageDesc = AZ::RHI::ImageDescriptor::Create2DArray(bindFlag, width, height, static_cast<uint16_t>(arraySize), format);
  163. imageDesc.m_mipLevels = 1;
  164. imageDesc.m_isCubemap = true;
  165. imageCreator.SetImageDescriptor(imageDesc);
  166. imageCreator.SetImageViewDescriptor(AZ::RHI::ImageViewDescriptor::CreateCubemap());
  167. // Create the mip chain
  168. AZ::RPI::ImageMipChainAssetCreator mipChainCreator;
  169. assetId.m_subId = 1;
  170. mipChainCreator.Begin(assetId, 1, 6);
  171. uint32_t pitch = width * pixelSize;
  172. AZ::RHI::ImageSubresourceLayout layout;
  173. layout.m_bytesPerImage = pixelDataSize;
  174. layout.m_rowCount = layout.m_bytesPerImage / pitch;
  175. layout.m_size = AZ::RHI::Size(width, height, 1);
  176. layout.m_bytesPerRow = pitch;
  177. mipChainCreator.BeginMip(layout);
  178. for (uint32_t i = 0; i < 6; ++i)
  179. {
  180. mipChainCreator.AddSubImage(pixels.data(), pixelDataSize);
  181. }
  182. mipChainCreator.EndMip();
  183. AZ::Data::Asset<AZ::RPI::ImageMipChainAsset> mipChainAsset;
  184. mipChainCreator.End(mipChainAsset);
  185. imageCreator.AddMipChainAsset(*mipChainAsset);
  186. // Finalize streaming image asset
  187. AZ::Data::Asset<AZ::RPI::StreamingImageAsset> imageAsset;
  188. imageCreator.End(imageAsset);
  189. return AZ::RPI::StreamingImage::FindOrCreate(imageAsset);
  190. }
  191. AZStd::string ResolvePath(const AZStd::string& path)
  192. {
  193. char resolvedPath[AZ_MAX_PATH_LEN] = {0};
  194. AZ::IO::FileIOBase::GetInstance()->ResolvePath(path.c_str(), resolvedPath, AZ_MAX_PATH_LEN);
  195. return resolvedPath;
  196. }
  197. bool IsFileUnderFolder(AZStd::string filePath, AZStd::string folder)
  198. {
  199. AzFramework::StringFunc::Path::Normalize(filePath);
  200. AzFramework::StringFunc::Path::Normalize(folder);
  201. AZStd::to_lower(filePath.begin(), filePath.end());
  202. AZStd::to_lower(folder.begin(), folder.end());
  203. auto relativePath = AZ::IO::FixedMaxPath(filePath.c_str()).LexicallyRelative(folder.c_str());
  204. if (!relativePath.empty() && !relativePath.Native().starts_with(".."))
  205. {
  206. return true;
  207. }
  208. return false;
  209. }
  210. } // namespace Utils
  211. } // namespace AtomSampleViewer