ShaderBuildArgumentsManager.h 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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/base.h>
  10. #include <AzCore/IO/Path/Path.h>
  11. #include "CommonFiles/CommonTypes.h"
  12. #include <Atom/RHI.Edit/ShaderBuildArguments.h>
  13. namespace UnitTest
  14. {
  15. class ShaderBuildArgumentsTests;
  16. }
  17. namespace AZ
  18. {
  19. namespace ShaderBuilder
  20. {
  21. //! This class manages a stack of ShaderBuildArguments.
  22. //! It simplifies command line argument definition at each level
  23. //! of the shader build hierarchy:
  24. //!
  25. //! {
  26. //! push(global arguments)
  27. //! {
  28. //! push(PlatformInfo arguments)
  29. //! {
  30. //! push(RHI arguments)
  31. //! {
  32. //! push(.shader arguments)
  33. //! {
  34. //! push(shader.supervariant arguments)
  35. //! ...
  36. //! -- build shader with current arguments. --
  37. //! ...
  38. //! pop()
  39. //! }
  40. //! pop()
  41. //! }
  42. //! pop()
  43. //! }
  44. //! pop()
  45. //! }
  46. //! pop()
  47. //! }
  48. //!
  49. //! At each push(), two set of arguments are necessary, the "remove" set and the "add" set.
  50. //! The idea is that it allows deep customization of all the shader build arguments by removing
  51. //! or adding arguments at each level.
  52. class ShaderBuildArgumentsManager final
  53. {
  54. public:
  55. AZ_CLASS_ALLOCATOR(ShaderBuildArgumentsManager, AZ::SystemAllocator);
  56. static constexpr char LogName[] = "ShaderBuildArgumentsManager";
  57. // The value of this registry key is customizable by the user.
  58. static constexpr char ConfigPathRegistryKey[] = "/O3DE/Atom/Shaders/Build/ConfigPath";
  59. static constexpr char DefaultConfigPathDirectory[] = "@gemroot:AtomShader@/Assets/Config/Shader";
  60. static constexpr char ShaderBuildOptionsJson[] = "shader_build_options.settings";
  61. static constexpr char PlatformsDir[] = "Platform";
  62. //! Always loads all the factory arguments provided by the Atom Gem. In addition
  63. //! it checks if the user customized all or some of the arguments with the registry key: @ConfigPathRegistryKey (see above)
  64. void Init();
  65. //! Pushes a new scope of arguments into the stack . The arguments to push are searched internally by the given @name,
  66. //! but if such arguments are not found, which is a common situation, then the current set of arguments at the top of the stack
  67. //! are pushed again on top of the stack, so subsequent calls to PopArgumentScope() work seamlessly.
  68. //! @param name Substring of the internally owned set of arguments.
  69. //! For example if the user wants to use the arguments for dx12 on Windows ("Windows.dx12"),
  70. //! then it is expected that this function should be called twice, as follows:
  71. //! PushArguments("Windows")
  72. //! PushArguments("dx12")
  73. //! The names come from the directory structure under the Platform/ folder:
  74. //! - Platform/
  75. //! - Windows/ (Platform name)
  76. //! - dx12/ (RHI name)
  77. //! - vulkan/ (RHI name)
  78. //! @returns The resulting (combined, with - and +) set of arguments at the top of the stack.
  79. const AZ::RHI::ShaderBuildArguments& PushArgumentScope(const AZStd::string& name);
  80. //! Similar to above, but the arguments being pushed are anonymous.
  81. //! @param removeArguments List of arguments to remove from the top of the stack.
  82. //! @param addArguments List of arguments to add to the top of the stack.
  83. //! @param definitions Additional arguments, specialized for the C-preprocessor, of the form "MACRO", or "MACRO=VALUE".
  84. //! @returns The resulting (combined, with - and +) set of arguments at the top of the stack.
  85. const AZ::RHI::ShaderBuildArguments& PushArgumentScope(const AZ::RHI::ShaderBuildArguments& removeArguments,
  86. const AZ::RHI::ShaderBuildArguments& addArguments,
  87. const AZStd::vector<AZStd::string>& definitions);
  88. //! @returns The resulting (combined, with - and +) set of arguments at the top of the stack.
  89. const AZ::RHI::ShaderBuildArguments& GetCurrentArguments() const;
  90. //! Your typical stack popping function.
  91. //! @remark: The "" (global) arguments are never popped, regardless of how many times this function is called.
  92. void PopArgumentScope();
  93. //! Finds the shader build config files from the default locations. Returns a map where the key is the name of the scope,
  94. //! and the value is a fully qualified file path.
  95. //! Remarks: Posible scope names are:
  96. //! "global"
  97. //! "<platform>". Example "Android", "Windows", etc
  98. //! "<platform>.<rhi>". Example "Windows.dx12" or "Windows.vulkan".
  99. static AZStd::unordered_map<AZStd::string, AZ::IO::FixedMaxPath> DiscoverConfigurationFiles();
  100. private:
  101. friend class ::UnitTest::ShaderBuildArgumentsTests;
  102. void Init(AZStd::unordered_map<AZStd::string, AZ::RHI::ShaderBuildArguments> && removeBuildArgumentsMap
  103. , AZStd::unordered_map<AZStd::string, AZ::RHI::ShaderBuildArguments> && addBuildArgumentsMap);
  104. //! @returns A fully qualified path where the factory settings, as provided by Atom, are found.
  105. static AZ::IO::FixedMaxPath GetDefaultConfigDirectoryPath();
  106. //! @returns A fully qualified path where the user customized command line arguments are found.
  107. //! The returned path will be empty if the user did not customize the path in the registry.
  108. static AZ::IO::FixedMaxPath GetUserConfigDirectoryPath();
  109. //! @param dirPath Starting directory for the search of shader_build_options.json files.
  110. //! @returns A map where the key is the name of the scope, and the value is a fully qualified file path.
  111. //! Remarks: Posible scope names are:
  112. //! "global"
  113. //! "<platform>". Example "Android", "Windows", etc
  114. //! "<platform>.<rhi>". Example "Windows.dx12" or "Windows.vulkan".
  115. static AZStd::unordered_map<AZStd::string, AZ::IO::FixedMaxPath> DiscoverConfigurationFilesInDirectory(const AZ::IO::FixedMaxPath& dirPath);
  116. const AZ::RHI::ShaderBuildArguments& PushArgumentsInternal(const AZStd::string& name, const AZ::RHI::ShaderBuildArguments& arguments);
  117. //! In this map we store which arguments should be removed for a fully qualified scope of arguments.
  118. //! A fully qualified scope name can be:
  119. //! "Windows" or "Windows.dx12" or "Windows.vulkan".
  120. AZStd::unordered_map<AZStd::string, AZ::RHI::ShaderBuildArguments> m_removeBuildArgumentsMap;
  121. //! In this map we store which arguments should be added for a fully qualified scope of arguments.
  122. //! A fully qualified scope name can be:
  123. //! "" (The global scope) or "Windows" or "Windows.dx12" or "Windows.vulkan".
  124. AZStd::unordered_map<AZStd::string, AZ::RHI::ShaderBuildArguments> m_addBuildArgumentsMap;
  125. AZStd::stack<AZ::RHI::ShaderBuildArguments> m_argumentsStack;
  126. AZStd::stack<AZStd::string> m_argumentsNameStack;
  127. };
  128. } // ShaderBuilder namespace
  129. } // AZ