Parcourir la source

Add a DrawItemType to the Shader-Items of a materialtype (#19120)

Signed-off-by: Karl Haubenwallner <[email protected]>
Karl Haubenwallner il y a 5 jours
Parent
commit
59dc761406
19 fichiers modifiés avec 374 ajouts et 155 suppressions
  1. 21 6
      Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialPipelineSourceData.h
  2. 8 1
      Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialTypeSourceData.h
  3. 9 4
      Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h
  4. 13 6
      Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialTypeAsset.h
  5. 48 25
      Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialTypeAssetCreator.h
  6. 29 2
      Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/ShaderCollection.h
  7. 1 0
      Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialTypeBuilder.cpp
  8. 1 1
      Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialPipelineSourceData.cpp
  9. 3 3
      Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp
  10. 15 4
      Gems/Atom/RPI/Code/Source/RPI.Public/MeshDrawPacket.cpp
  11. 9 6
      Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp
  12. 16 11
      Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAsset.cpp
  13. 11 5
      Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAssetCreator.cpp
  14. 16 4
      Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/ShaderCollection.cpp
  15. 18 3
      Gems/Atom/RPI/Code/Tests/Material/LuaMaterialFunctorTests.cpp
  16. 31 24
      Gems/Atom/RPI/Code/Tests/Material/MaterialTests.cpp
  17. 121 45
      Gems/Atom/RPI/Code/Tests/Material/MaterialTypeAssetTests.cpp
  18. 3 4
      Gems/Atom/RPI/Code/Tests/Material/MaterialTypeSourceDataTests.cpp
  19. 1 1
      Gems/Terrain/Code/Source/TerrainRenderer/TerrainMeshManager.cpp

+ 21 - 6
Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialPipelineSourceData.h

@@ -7,12 +7,13 @@
  */
 #pragma once
 
-#include <AzCore/RTTI/RTTI.h>
-#include <AzCore/Memory/SystemAllocator.h>
-#include <AzCore/std/string/string.h>
-#include <AzCore/std/containers/vector.h>
 #include <Atom/RPI.Edit/Configuration.h>
 #include <Atom/RPI.Edit/Material/MaterialPropertySourceData.h>
+#include <Atom/RPI.Reflect/Material/ShaderCollection.h>
+#include <AzCore/Memory/SystemAllocator.h>
+#include <AzCore/RTTI/RTTI.h>
+#include <AzCore/std/containers/vector.h>
+#include <AzCore/std/string/string.h>
 
 namespace AZ
 {
@@ -39,16 +40,30 @@ namespace AZ
 
                 AZStd::string m_shader; //!< Relative path to a template .shader file that will configure the final shader asset.
                 AZStd::string m_azsli; //!< Relative path to a template .azsli file that will be stitched together with material-specific shader code.
+
                 Name m_shaderTag; //!< tag to identify the shader, particularly in lua functors
+                //! Type of the generated draw-items
+                using DrawItemType = AZ::RPI::ShaderCollection::Item::DrawItemType;
+                DrawItemType m_drawItemType = DrawItemType::Raster;
 
                 bool operator==(const ShaderTemplate& rhs) const
                 {
-                    return m_shader == rhs.m_shader && m_azsli == rhs.m_azsli && m_shaderTag == rhs.m_shaderTag;
+                    return m_shader == rhs.m_shader && m_azsli == rhs.m_azsli && m_shaderTag == rhs.m_shaderTag &&
+                        m_drawItemType == rhs.m_drawItemType;
                 }
 
                 bool operator<(const ShaderTemplate& rhs) const
                 {
-                    return AZStd::tuple(m_shader, m_azsli, m_shaderTag.GetHash()) < AZStd::tuple(rhs.m_shader, rhs.m_azsli, rhs.m_shaderTag.GetHash());
+                    return AZStd::tuple(
+                               AZStd::string_view(m_shader),
+                               AZStd::string_view(m_azsli),
+                               m_shaderTag.GetHash(),
+                               static_cast<int32_t>(m_drawItemType)) <
+                        AZStd::tuple(
+                               AZStd::string_view(rhs.m_shader),
+                               AZStd::string_view(rhs.m_azsli),
+                               rhs.m_shaderTag.GetHash(),
+                               static_cast<int32_t>(rhs.m_drawItemType));
                 }
             };
 

+ 8 - 1
Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialTypeSourceData.h

@@ -10,10 +10,13 @@
 
 #include <AzCore/RTTI/TypeInfo.h>
 #include <AzCore/std/containers/map.h>
+
 #include <Atom/RPI.Reflect/Base.h>
 #include <Atom/RPI.Reflect/Material/MaterialPropertyDescriptor.h>
-#include <Atom/RPI.Reflect/Material/MaterialVersionUpdate.h>
 #include <Atom/RPI.Reflect/Material/MaterialTypeAssetCreator.h>
+#include <Atom/RPI.Reflect/Material/MaterialVersionUpdate.h>
+#include <Atom/RPI.Reflect/Material/ShaderCollection.h>
+
 #include <Atom/RPI.Edit/Configuration.h>
 #include <Atom/RPI.Edit/Material/MaterialFunctorSourceData.h>
 #include <Atom/RPI.Edit/Material/MaterialPropertyId.h>
@@ -138,6 +141,10 @@ namespace AZ
                 //! Unique tag to identify the shader, particularly in lua functors
                 AZ::Name m_shaderTag;
 
+                //! Type of the generated draw-items
+                using DrawItemType = AZ::RPI::ShaderCollection::Item::DrawItemType;
+                DrawItemType m_drawItemType = DrawItemType::Raster;
+
                 //! This list provides a way for users to set shader option values in a 'hard-coded' way rather than connecting them to material properties.
                 //! These are optional and the list will usually be empty; most options will either get set from a material property connection,
                 //! or will use the default value from the shader. 

+ 9 - 4
Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h

@@ -94,17 +94,22 @@ namespace AZ
 
             //! Returns the shader resource group layout that has per-object frequency. What constitutes an "object" is an
             //! agreement between the FeatureProcessor and the shaders, but an example might be world-transform for a model.
-            //! All shaders in a material will have the same per-object SRG layout.
+            //! All shaders with the same DrawItemType in a material will have the same per-object SRG layout.
             //! @param supervariantIndex: supervariant index to get the layout from.
-            const RHI::Ptr<RHI::ShaderResourceGroupLayout>& GetObjectSrgLayout(const SupervariantIndex& supervariantIndex) const;
+            const RHI::Ptr<RHI::ShaderResourceGroupLayout>& GetObjectSrgLayout(
+                const SupervariantIndex& supervariantIndex,
+                const ShaderCollection::Item::DrawItemType drawItemType = ShaderCollection::Item::DrawItemType::Raster) const;
 
             //! Same as above but accepts the supervariant name. There's a minor penalty when using this function
             //! because it will discover the index from the name.
-            const RHI::Ptr<RHI::ShaderResourceGroupLayout>& GetObjectSrgLayout(const AZ::Name& supervariantName) const;
+            const RHI::Ptr<RHI::ShaderResourceGroupLayout>& GetObjectSrgLayout(
+                const AZ::Name& supervariantName,
+                const ShaderCollection::Item::DrawItemType drawItemType = ShaderCollection::Item::DrawItemType::Raster) const;
 
             //! Just like the original GetObjectSrgLayout() where it uses the index of the default supervariant.
             //! See the definition of DefaultSupervariantIndex.
-            const RHI::Ptr<RHI::ShaderResourceGroupLayout>& GetObjectSrgLayout() const;
+            const RHI::Ptr<RHI::ShaderResourceGroupLayout>& GetObjectSrgLayout(
+                const ShaderCollection::Item::DrawItemType drawItemType = ShaderCollection::Item::DrawItemType::Raster) const;
 
             //! Returns a layout that includes a list of MaterialPropertyDescriptors for each material property.
             const MaterialPropertiesLayout* GetMaterialPropertiesLayout() const;

+ 13 - 6
Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialTypeAsset.h

@@ -123,18 +123,24 @@ namespace AZ
             //! agreement between the FeatureProcessor and the shaders, but an example might be world-transform for a model.
             //! All shaders in a material will have the same per-object SRG layout.
             //! @param supervariantIndex: supervariant index to get the layout from.
-            const RHI::Ptr<RHI::ShaderResourceGroupLayout>& GetObjectSrgLayout(const SupervariantIndex& supervariantIndex) const;
+            const RHI::Ptr<RHI::ShaderResourceGroupLayout>& GetObjectSrgLayout(
+                const SupervariantIndex& supervariantIndex,
+                const ShaderCollection::Item::DrawItemType drawItemType = ShaderCollection::Item::DrawItemType::Raster) const;
 
             //! Same as above but accepts the supervariant name. There's a minor penalty when using this function
-            //! because it will discover the index from the name.  
-            const RHI::Ptr<RHI::ShaderResourceGroupLayout>& GetObjectSrgLayout(const Name& supervariantName) const;
+            //! because it will discover the index from the name.
+            const RHI::Ptr<RHI::ShaderResourceGroupLayout>& GetObjectSrgLayout(
+                const Name& supervariantName,
+                const ShaderCollection::Item::DrawItemType drawItemType = ShaderCollection::Item::DrawItemType::Raster) const;
 
             //! Just like the original GetObjectSrgLayout() where it uses the index of the default supervariant.
             //! See the definition of DefaultSupervariantIndex.
-            const RHI::Ptr<RHI::ShaderResourceGroupLayout>& GetObjectSrgLayout() const;
+            const RHI::Ptr<RHI::ShaderResourceGroupLayout>& GetObjectSrgLayout(
+                const ShaderCollection::Item::DrawItemType drawItemType = ShaderCollection::Item::DrawItemType::Raster) const;
 
             //! Returns a ShaderAsset from @m_shaderCollection that contains the ObjectSrg layout.
-            const Data::Asset<ShaderAsset>& GetShaderAssetForObjectSrg() const;
+            const Data::Asset<ShaderAsset>& GetShaderAssetForObjectSrg(
+                const ShaderCollection::Item::DrawItemType drawItemType = ShaderCollection::Item::DrawItemType::Raster) const;
 
             //! Returns a layout that includes a list of MaterialPropertyDescriptors for each material property.
             const MaterialPropertiesLayout* GetMaterialPropertiesLayout() const;
@@ -202,7 +208,8 @@ namespace AZ
             //! to the shader rather than duplicate the SRG layouts to avoid duplication and also because the ShaderAsset
             //! is needed to create an instance of the SRG so it's convenient to just keep a reference to the ShaderAsset.
             Data::Asset<ShaderAsset> m_shaderWithMaterialSrg;
-            Data::Asset<ShaderAsset> m_shaderWithObjectSrg;
+            AZStd::array<Data::Asset<ShaderAsset>, AZStd::to_underlying(ShaderCollection::Item::DrawItemType::MaxCount)>
+                m_shaderWithObjectSrg;
 
             //! The version of this MaterialTypeAsset. If the version is greater than 1, actions performed
             //! to update this MaterialTypeAsset will be in m_materialVersionUpdateMap

+ 48 - 25
Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialTypeAssetCreator.h

@@ -33,6 +33,8 @@ namespace AZ
             //! Begin creating a MaterialTypeAsset
             void Begin(const Data::AssetId& assetId);
 
+            using DrawItemType = AZ::RPI::ShaderCollection::Item::DrawItemType;
+
             //! Adds a shader to the built-in shader collection, which will be run for this material.
             //! @param shaderTag Must be unique within the material type's list of shaders.
             //! @param materialPipelineName Identifies a specific MaterialPipelinePayload that this shader should be added to.
@@ -41,6 +43,7 @@ namespace AZ
                 const AZ::Data::Asset<ShaderAsset>& shaderAsset,
                 const ShaderVariantId& shaderVariantId = {},
                 const AZ::Name& shaderTag = {},
+                const DrawItemType drawItemType = DrawItemType::Raster,
                 const AZ::Name& materialPipelineName = MaterialPipelineNone);
 
             //! Sets the version of the MaterialTypeAsset
@@ -58,9 +61,13 @@ namespace AZ
             //! Starts creating a material property.
             //! Note that EndMaterialProperty() must be called before calling SetMaterialPropertyValue(). Similarly,
             //! The property will not appear in GetMaterialPropertiesLayout() until EndMaterialProperty() is called.
-            //! @param materialPipelineName For internal material properties, this indicates which material pipeline the property is for.
+            //! @param materialPipelineName For internal material properties, this indicates which material pipeline the property is
+            //! for.
             //!                             For main material properties, use MaterialPipelineNone.
-            void BeginMaterialProperty(const Name& materialPropertyName, MaterialPropertyDataType dataType, const AZ::Name& materialPipelineName = MaterialPipelineNone);
+            void BeginMaterialProperty(
+                const Name& materialPropertyName,
+                MaterialPropertyDataType dataType,
+                const AZ::Name& materialPipelineName = MaterialPipelineNone);
 
             //! Adds an output mapping from the current material property to a ShaderPararameter field.
             void ConnectMaterialPropertyToShaderParameter(const Name& shaderInputName);
@@ -85,21 +92,33 @@ namespace AZ
             //! Finishes creating a material property.
             void EndMaterialProperty();
 
-            //! @param materialPipelineName For internal material properties, this indicates which MaterialPipelinePlayload's property to update.
+            //! @param materialPipelineName For internal material properties, this indicates which MaterialPipelinePlayload's property
+            //! to update.
             //!                             For main material properties, use MaterialPipelineNone.
-            void SetPropertyValue(const Name& name, const Data::Asset<ImageAsset>& imageAsset, const AZ::Name& materialPipelineName = MaterialPipelineNone);
-            void SetPropertyValue(const Name& name, const Data::Asset<StreamingImageAsset>& imageAsset, const AZ::Name& materialPipelineName = MaterialPipelineNone);
-            void SetPropertyValue(const Name& name, const Data::Asset<AttachmentImageAsset>& imageAsset, const AZ::Name& materialPipelineName = MaterialPipelineNone);
+            void SetPropertyValue(
+                const Name& name, const Data::Asset<ImageAsset>& imageAsset, const AZ::Name& materialPipelineName = MaterialPipelineNone);
+            void SetPropertyValue(
+                const Name& name,
+                const Data::Asset<StreamingImageAsset>& imageAsset,
+                const AZ::Name& materialPipelineName = MaterialPipelineNone);
+            void SetPropertyValue(
+                const Name& name,
+                const Data::Asset<AttachmentImageAsset>& imageAsset,
+                const AZ::Name& materialPipelineName = MaterialPipelineNone);
 
             //! Sets a property value using data in AZStd::variant-based MaterialPropertyValue. The contained data must match
             //! the data type of the property. For type Image, the value must be a Data::Asset<ImageAsset>.
-            //! @param materialPipelineName For internal material properties, this indicates which MaterialPipelinePayload's property to update.
+            //! @param materialPipelineName For internal material properties, this indicates which MaterialPipelinePayload's property to
+            //! update.
             //!                             For main material properties, use MaterialPipelineNone.
-            void SetPropertyValue(const Name& name, const MaterialPropertyValue& value, const AZ::Name& materialPipelineName = MaterialPipelineNone);
+            void SetPropertyValue(
+                const Name& name, const MaterialPropertyValue& value, const AZ::Name& materialPipelineName = MaterialPipelineNone);
 
             //! Adds a MaterialFunctor.
-            //! Material functors provide custom logic and calculations to configure shaders, render states, and more.See MaterialFunctor.h for details.
-            //! @param materialPipelineName Identifies a MaterialPipelinePayload that this functor should be added to. For MaterialPipelineNone, 
+            //! Material functors provide custom logic and calculations to configure shaders, render states, and more.See
+            //! MaterialFunctor.h for details.
+            //! @param materialPipelineName Identifies a MaterialPipelinePayload that this functor should be added to. For
+            //! MaterialPipelineNone,
             //!                             the functor will be used for the main ShaderCollection that applies to all pipelines.
             void AddMaterialFunctor(const Ptr<MaterialFunctor>& functor, const AZ::Name& materialPipelineName = MaterialPipelineNone);
 
@@ -127,9 +146,10 @@ namespace AZ
 
             //! This provides access to the material ShaderResourceGroupLayout being used for the MaterialTypeAsset.
             //! This is needed by MaterialTypeSourceData to initialize functor objects.
-            //! The same layout object can be retrieved from the ShaderAssets passed to the creator, but this function 
+            //! The same layout object can be retrieved from the ShaderAssets passed to the creator, but this function
             //! is provided for convenience.
-            //! @return A valid pointer if a ShaderAsset with a material ShaderResourceGroupLayout was added. Otherwise, returns nullptr.
+            //! @return A valid pointer if a ShaderAsset with a material ShaderResourceGroupLayout was added. Otherwise, returns
+            //! nullptr.
             const RHI::ShaderResourceGroupLayout* GetMaterialShaderResourceGroupLayout() const;
 
             void UpdateShaderParameterConnections();
@@ -137,15 +157,15 @@ namespace AZ
             bool End(Data::Asset<MaterialTypeAsset>& result);
 
         private:
-
             void AddMaterialProperty(MaterialPropertyDescriptor&& materialProperty, const AZ::Name& materialPipelineName);
-            
+
             bool PropertyCheck(TypeId typeId, const Name& propertyName, const AZ::Name& materialPipelineName);
-                
-            //! The material type holds references to shader assets that contain SRGs that are supposed to be the same across all passes in the material.
-            //! This function searches for an SRG given a @bindingSlot. If a valid one is found it makes sure it is the same across all shaders
-            //! and records it in @srgShaderAssetToUpdate.
-            //! @srgShaderAssetToUpdate Previously found shader asset with the desired SRG. If Invalid, this will be filled with the shader asset
+
+            //! The material type holds references to shader assets that contain SRGs that are supposed to be the same across all passes
+            //! in the material. This function searches for an SRG given a @bindingSlot. If a valid one is found it makes sure it is the
+            //! same across all shaders and records it in @srgShaderAssetToUpdate.
+            //! @srgShaderAssetToUpdate Previously found shader asset with the desired SRG. If Invalid, this will be filled with the
+            //! shader asset
             //!     where the bindingSlot was found. If not Invalid, this will validate that the same SRG is used by newShaderAsset.
             //! @bindingSlot  The binding slot ID of the SRG to fetch from newShaderAsset.
             bool UpdateShaderAssetForShaderResourceGroup(
@@ -156,18 +176,21 @@ namespace AZ
 
             //! Saves the per-material SRG layout in m_shaderResourceGroupLayout for easier access
             void CacheMaterialSrgLayout();
-            
+
             bool ValidateMaterialVersion();
             bool ValidateBeginMaterialProperty();
             bool ValidateEndMaterialProperty();
 
             MaterialTypeAsset::MaterialPipelinePayload& GetMaterialPipelinePayload(const AZ::Name& materialPipelineName);
 
-            
-            MaterialPropertiesLayout* m_materialPropertiesLayout = nullptr; //!< Cached pointer to the MaterialPropertiesLayout being created
-            const RHI::ShaderResourceGroupLayout* m_materialShaderResourceGroupLayout = nullptr; //!< The per-material ShaderResourceGroup layout
-            MaterialPropertyDescriptor m_wipMaterialProperty; //!< Material property being created. Is valid between BeginMaterialProperty() and EndMaterialProperty()
-            Name m_wipMaterialPropertyPipeline; //!< Tracks which MaterialPipelinePayload the material property is being created for, if any.
+            MaterialPropertiesLayout* m_materialPropertiesLayout =
+                nullptr; //!< Cached pointer to the MaterialPropertiesLayout being created
+            const RHI::ShaderResourceGroupLayout* m_materialShaderResourceGroupLayout =
+                nullptr; //!< The per-material ShaderResourceGroup layout
+            MaterialPropertyDescriptor m_wipMaterialProperty; //!< Material property being created. Is valid between
+                                                              //!< BeginMaterialProperty() and EndMaterialProperty()
+            Name m_wipMaterialPropertyPipeline; //!< Tracks which MaterialPipelinePayload the material property is being created for, if
+                                                //!< any.
         };
 
     } // namespace RPI

+ 29 - 2
Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/ShaderCollection.h

@@ -50,11 +50,30 @@ namespace AZ
                 //! Required for use in containers; not meant to be called directly.
                 Item();
 
+                // type of the generated draw-item the Rendering-Pass expects
+                enum class DrawItemType : uint32_t
+                {
+                    Raster = 0, // the shader expects a default draw item for a rasterpass (default)
+                    Dispatch, // the shader expects a dispatch-item for a compute-pass
+                    Deferred, // the shader expects a fullscreen draw item for a deferred rendering pass
+                    RayTracing, // the shader expects shader libraries for a raytracing shader table
+                    Custom, // The draw-item will be created in a custom gem
+                    MaxCount // count for array indexing
+                };
+
                 //! @param shaderAsset The ShaderAsset represented by this item.
                 //! @param shaderTag Unique tag to identify this item.
                 //! @param variantId The the initial state of shader option values for use with this shader item.
-                Item(const Data::Asset<ShaderAsset>& shaderAsset, const AZ::Name& shaderTag, ShaderVariantId variantId = ShaderVariantId{});
-                Item(Data::Asset<ShaderAsset>&& shaderAsset, const AZ::Name& shaderTag, ShaderVariantId variantId = ShaderVariantId{});
+                Item(
+                    const Data::Asset<ShaderAsset>& shaderAsset,
+                    const AZ::Name& shaderTag,
+                    DrawItemType drawItemType = DrawItemType::Raster,
+                    ShaderVariantId variantId = ShaderVariantId{});
+                Item(
+                    Data::Asset<ShaderAsset>&& shaderAsset,
+                    const AZ::Name& shaderTag,
+                    DrawItemType drawItemType = DrawItemType::Raster,
+                    ShaderVariantId variantId = ShaderVariantId{});
 
                 const Data::Asset<ShaderAsset>& GetShaderAsset() const;
 
@@ -102,6 +121,11 @@ namespace AZ
                 // Only returns false if @m_shaderAsset is not ready.
                 bool InitializeShaderOptionGroup();
 
+                DrawItemType GetDrawItemType() const
+                {
+                    return m_drawItemType;
+                }
+
             private:
                 Data::Asset<ShaderAsset> m_shaderAsset;
                 ShaderVariantId m_shaderVariantId;       //!< Temporarily holds the ShaderVariantId, used for serialization. This will be copied to/from m_shaderOptionGroup.
@@ -112,6 +136,7 @@ namespace AZ
                 AZStd::unordered_set<ShaderOptionIndex> m_ownedShaderOptionIndices; //!< Set of shader options in this shader that are owned by the material.
                 bool m_enabled = true;                   //!< Disabled items will not be included in the final draw packet that gets sent to the renderer.
                 AZ::Name m_shaderTag;                    //!< Unique tag that identifies this item
+                DrawItemType m_drawItemType = DrawItemType::Raster; //!< Type of draw-item that this shader expects
             };
 
             using iterator = AZStd::vector<Item>::iterator;
@@ -145,5 +170,7 @@ namespace AZ
             NameReflectionMapForIndex m_shaderTagIndexMap;
         };
 
+        AZ_TYPE_INFO_SPECIALIZE(ShaderCollection::Item::DrawItemType, "{967D8A25-E303-44E2-A0D0-0F75C8F9CEA7}");
+
     } // namespace RPI
 } // namespace AZ

+ 1 - 0
Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialTypeBuilder.cpp

@@ -774,6 +774,7 @@ namespace AZ
                     MaterialTypeSourceData::ShaderVariantReferenceData shaderVariantReferenceData;
                     shaderVariantReferenceData.m_shaderFilePath = AZ::IO::Path{ outputShaderFilePath.Filename() }.c_str();
                     shaderVariantReferenceData.m_shaderTag = shaderTemplate.m_shaderTag;
+                    shaderVariantReferenceData.m_drawItemType = shaderTemplate.m_drawItemType;
 
                     // Files in the cache, including intermediate files, end up using lower case for all files and folders. We have to match
                     // this in the output .materialtype file, because the asset system's source dependencies are case-sensitive on some

+ 1 - 1
Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialPipelineSourceData.cpp

@@ -25,7 +25,7 @@ namespace AZ
                     ->Field("shader", &ShaderTemplate::m_shader)
                     ->Field("azsli", &ShaderTemplate::m_azsli)
                     ->Field("tag", &ShaderTemplate::m_shaderTag)
-                    ;
+                    ->Field("type", &ShaderTemplate::m_drawItemType);
 
                 serializeContext->Class<RuntimeControls>()
                     ->Version(1)

+ 3 - 3
Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp

@@ -92,8 +92,8 @@ namespace AZ
                     ->Version(2)
                     ->Field("file", &ShaderVariantReferenceData::m_shaderFilePath)
                     ->Field("tag", &ShaderVariantReferenceData::m_shaderTag)
-                    ->Field("options", &ShaderVariantReferenceData::m_shaderOptionValues)
-                    ;
+                    ->Field("type", &ShaderVariantReferenceData::m_drawItemType)
+                    ->Field("options", &ShaderVariantReferenceData::m_shaderOptionValues);
 
                 serializeContext->Class<PropertyGroup>()
                     ->Version(2)
@@ -961,7 +961,7 @@ namespace AZ
                     }
 
                     materialTypeAssetCreator.AddShader(
-                        shaderAsset, options.GetShaderVariantId(), shaderRef.m_shaderTag, materialPipelineName);
+                        shaderAsset, options.GetShaderVariantId(), shaderRef.m_shaderTag, shaderRef.m_drawItemType, materialPipelineName);
 
                     // Gather UV names
                     const ShaderInputContract& shaderInputContract = shaderAsset->GetInputContract();

+ 15 - 4
Gems/Atom/RPI/Code/Source/RPI.Public/MeshDrawPacket.cpp

@@ -328,8 +328,17 @@ namespace AZ
                 {
                     return false;
                 }
-
-                const bool isRasterShader = (shaderItem.GetShaderAsset()->GetPipelineStateType() == RHI::PipelineStateType::Draw);
+                bool isRasterShader = true;
+                if (shaderItem.GetDrawItemType() == RPI::ShaderCollection::Item::DrawItemType::Raster)
+                {
+                    // backwards compatability: DrawItemType::Raster is the fallback type if none is provided, and we supported
+                    // dispatch-items before the DrawItemType, using the piplineState-Type to determine if we need a dispatch item.
+                    isRasterShader = (shaderItem.GetShaderAsset()->GetPipelineStateType() == RHI::PipelineStateType::Draw);
+                }
+                else if (shaderItem.GetDrawItemType() == RPI::ShaderCollection::Item::DrawItemType::Dispatch)
+                {
+                    isRasterShader = false;
+                }
                 if (isRasterShader && !parentScene.HasOutputForPipelineState(drawListTag))
                 {
                     // drawListTag not found in this scene, so don't render this item
@@ -474,7 +483,7 @@ namespace AZ
                     AZ_Error(
                         "MeshDrawPacket",
                         (!m_rootConstantsLayout && !HasRootConstants(rootConstantsLayout)) ||
-                        (m_rootConstantsLayout && rootConstantsLayout && m_rootConstantsLayout->GetHash() == rootConstantsLayout->GetHash()),
+                            (m_rootConstantsLayout && rootConstantsLayout && m_rootConstantsLayout->GetHash() == rootConstantsLayout->GetHash()),
                         "Shader %s has mis-matched root constant layout in material %s. "
                         "All draw items in a draw packet need to share the same root constants layout. This means that each pass "
                         "(e.g. Depth, Shadows, Forward, MotionVectors) for a given materialtype should use the same layout.",
@@ -525,7 +534,9 @@ namespace AZ
             m_material->ForAllShaderItems(
                 [&](const Name& materialPipelineName, const ShaderCollection::Item& shaderItem)
                 {
-                    if (shaderItem.IsEnabled())
+                    if (shaderItem.IsEnabled() &&
+                        (shaderItem.GetDrawItemType() == RPI::ShaderCollection::Item::DrawItemType::Raster ||
+                         shaderItem.GetDrawItemType() == RPI::ShaderCollection::Item::DrawItemType::Dispatch))
                     {
                         if (shaderList.size() == RHI::DrawPacketBuilder::DrawItemCountMax)
                         {

+ 9 - 6
Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp

@@ -93,19 +93,22 @@ namespace AZ
             return m_materialTypeAsset->GetMaterialSrgLayout();
         }
 
-        const RHI::Ptr<RHI::ShaderResourceGroupLayout>& MaterialAsset::GetObjectSrgLayout(const SupervariantIndex& supervariantIndex) const
+        const RHI::Ptr<RHI::ShaderResourceGroupLayout>& MaterialAsset::GetObjectSrgLayout(
+            const SupervariantIndex& supervariantIndex, const ShaderCollection::Item::DrawItemType drawItemType) const
         {
-            return m_materialTypeAsset->GetObjectSrgLayout(supervariantIndex);
+            return m_materialTypeAsset->GetObjectSrgLayout(supervariantIndex, drawItemType);
         }
 
-        const RHI::Ptr<RHI::ShaderResourceGroupLayout>& MaterialAsset::GetObjectSrgLayout(const AZ::Name& supervariantName) const
+        const RHI::Ptr<RHI::ShaderResourceGroupLayout>& MaterialAsset::GetObjectSrgLayout(
+            const AZ::Name& supervariantName, const ShaderCollection::Item::DrawItemType drawItemType) const
         {
-            return m_materialTypeAsset->GetObjectSrgLayout(supervariantName);
+            return m_materialTypeAsset->GetObjectSrgLayout(supervariantName, drawItemType);
         }
 
-        const RHI::Ptr<RHI::ShaderResourceGroupLayout>& MaterialAsset::GetObjectSrgLayout() const
+        const RHI::Ptr<RHI::ShaderResourceGroupLayout>& MaterialAsset::GetObjectSrgLayout(
+            const ShaderCollection::Item::DrawItemType drawItemType) const
         {
-            return m_materialTypeAsset->GetObjectSrgLayout();
+            return m_materialTypeAsset->GetObjectSrgLayout(drawItemType);
         }
 
         const MaterialPropertiesLayout* MaterialAsset::GetMaterialPropertiesLayout() const

+ 16 - 11
Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAsset.cpp

@@ -160,35 +160,40 @@ namespace AZ
         }
 
         const RHI::Ptr<RHI::ShaderResourceGroupLayout>& MaterialTypeAsset::GetObjectSrgLayout(
-            const SupervariantIndex& supervariantIndex) const
+            const SupervariantIndex& supervariantIndex, const ShaderCollection::Item::DrawItemType drawItemType) const
         {
-            if (!m_shaderWithObjectSrg)
+            if (!m_shaderWithObjectSrg[AZStd::to_underlying(drawItemType)])
             {
                 return RHI::NullSrgLayout;
             }
 
-            return m_shaderWithObjectSrg->FindShaderResourceGroupLayout(RPI::SrgBindingSlot::Object, supervariantIndex);
+            return m_shaderWithObjectSrg[AZStd::to_underlying(drawItemType)]->FindShaderResourceGroupLayout(
+                RPI::SrgBindingSlot::Object, supervariantIndex);
         }
 
-        const RHI::Ptr<RHI::ShaderResourceGroupLayout>& MaterialTypeAsset::GetObjectSrgLayout(const AZ::Name& supervariantName) const
+        const RHI::Ptr<RHI::ShaderResourceGroupLayout>& MaterialTypeAsset::GetObjectSrgLayout(
+            const AZ::Name& supervariantName, const ShaderCollection::Item::DrawItemType drawItemType) const
         {
-            if (!m_shaderWithObjectSrg)
+            if (!m_shaderWithObjectSrg[AZStd::to_underlying(drawItemType)])
             {
                 return RHI::NullSrgLayout;
             }
 
-            auto supervariantIndex = m_shaderWithObjectSrg->GetSupervariantIndex(supervariantName);
-            return m_shaderWithObjectSrg->FindShaderResourceGroupLayout(RPI::SrgBindingSlot::Object, supervariantIndex);
+            auto supervariantIndex = m_shaderWithObjectSrg[AZStd::to_underlying(drawItemType)]->GetSupervariantIndex(supervariantName);
+            return m_shaderWithObjectSrg[AZStd::to_underlying(drawItemType)]->FindShaderResourceGroupLayout(
+                RPI::SrgBindingSlot::Object, supervariantIndex);
         }
 
-        const RHI::Ptr<RHI::ShaderResourceGroupLayout>& MaterialTypeAsset::GetObjectSrgLayout() const
+        const RHI::Ptr<RHI::ShaderResourceGroupLayout>& MaterialTypeAsset::GetObjectSrgLayout(
+            const ShaderCollection::Item::DrawItemType drawItemType) const
         {
-            return GetObjectSrgLayout(DefaultSupervariantIndex);
+            return GetObjectSrgLayout(DefaultSupervariantIndex, drawItemType);
         }
 
-        const Data::Asset<ShaderAsset>& MaterialTypeAsset::GetShaderAssetForObjectSrg() const
+        const Data::Asset<ShaderAsset>& MaterialTypeAsset::GetShaderAssetForObjectSrg(
+            const ShaderCollection::Item::DrawItemType drawItemType) const
         {
-            return m_shaderWithObjectSrg;
+            return m_shaderWithObjectSrg[AZStd::to_underlying(drawItemType)];
         }
 
         const MaterialPropertiesLayout* MaterialTypeAsset::GetMaterialPropertiesLayout() const

+ 11 - 5
Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAssetCreator.cpp

@@ -117,6 +117,7 @@ namespace AZ
             const AZ::Data::Asset<ShaderAsset>& shaderAsset,
             const ShaderVariantId& shaderVariantId,
             const AZ::Name& shaderTag,
+            const DrawItemType drawItemType,
             const AZ::Name& materialPipelineName)
         {
             if (ValidateIsReady() && ValidateNotNull(shaderAsset, "ShaderAsset"))
@@ -133,15 +134,17 @@ namespace AZ
 
                 AZ::Name finalShaderTag = !shaderTag.IsEmpty() ? shaderTag : AZ::Name{AZ::Uuid::CreateRandom().ToFixedString()};
 
-                shaderCollection->m_shaderItems.push_back(ShaderCollection::Item{shaderAsset, finalShaderTag, shaderVariantId});
+                shaderCollection->m_shaderItems.push_back(
+                    ShaderCollection::Item{ shaderAsset, finalShaderTag, drawItemType, shaderVariantId });
                 if (!shaderCollection->m_shaderTagIndexMap.Insert(finalShaderTag, RHI::Handle<uint32_t>(shaderCollection->m_shaderItems.size() - 1)))
                 {
                     ReportError("Failed to insert shader tag '%s' for pipeline '%s'. Shader tag must be unique.", finalShaderTag.GetCStr(), materialPipelineName.GetCStr());
                 }
 
-                UpdateShaderAssetForShaderResourceGroup(m_asset->m_shaderWithMaterialSrg, shaderAsset, SrgBindingSlot::Material, "material");
-                UpdateShaderAssetForShaderResourceGroup(m_asset->m_shaderWithObjectSrg, shaderAsset, SrgBindingSlot::Object, "object");
-
+                UpdateShaderAssetForShaderResourceGroup(
+                    m_asset->m_shaderWithMaterialSrg, shaderAsset, SrgBindingSlot::Material, "material");
+                UpdateShaderAssetForShaderResourceGroup(
+                    m_asset->m_shaderWithObjectSrg[AZStd::to_underlying(drawItemType)], shaderAsset, SrgBindingSlot::Object, "object");
                 CacheMaterialSrgLayout();
             }
         }
@@ -570,7 +573,10 @@ namespace AZ
 
             if (!foundShaderOptions)
             {
-                ReportError("Material property '%s': Material contains no shaders with option '%s'.", m_wipMaterialProperty.GetName().GetCStr(), shaderOptionName.GetCStr());
+                ReportWarning(
+                    "Material property '%s': Material contains no shaders with option '%s'.",
+                    m_wipMaterialProperty.GetName().GetCStr(),
+                    shaderOptionName.GetCStr());
                 return;
             }
         }

+ 16 - 4
Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/ShaderCollection.cpp

@@ -72,15 +72,22 @@ namespace AZ
         {
             if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
             {
+                serializeContext->Enum<ShaderCollection::Item::DrawItemType>()
+                    ->Value("Raster", ShaderCollection::Item::DrawItemType::Raster)
+                    ->Value("Dispatch", ShaderCollection::Item::DrawItemType::Dispatch)
+                    ->Value("Deferred", ShaderCollection::Item::DrawItemType::Deferred)
+                    ->Value("RayTracing", ShaderCollection::Item::DrawItemType::RayTracing)
+                    ->Value("Custom", ShaderCollection::Item::DrawItemType::Custom);
+
                 serializeContext->Class<ShaderCollection::Item>()
-                    ->Version(6)
+                    ->Version(7)
                     ->EventHandler<ShaderVariantReferenceSerializationEvents>()
                     ->Field("ShaderAsset", &ShaderCollection::Item::m_shaderAsset)
                     ->Field("ShaderVariantId", &ShaderCollection::Item::m_shaderVariantId)
                     ->Field("Enabled", &ShaderCollection::Item::m_enabled)
                     ->Field("OwnedShaderOptionIndices", &ShaderCollection::Item::m_ownedShaderOptionIndices)
                     ->Field("ShaderTag", &ShaderCollection::Item::m_shaderTag)
-                    ;
+                    ->Field("DrawItemType", &ShaderCollection::Item::m_drawItemType);
             }
 
             if (BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context))
@@ -93,6 +100,7 @@ namespace AZ
                     ->Method("GetShaderAssetId", &Item::GetShaderAssetId)
                     ->Method("GetShaderVariantId", &Item::GetShaderVariantId)
                     ->Method("GetShaderOptionGroup", &Item::GetShaderOptionGroup)
+                    ->Method("GetDrawItemType", &Item::GetDrawItemType)
                     ->Method("MaterialOwnsShaderOption", static_cast<bool (Item::*)(const Name&) const>(&Item::MaterialOwnsShaderOption));
             }
         }
@@ -172,20 +180,24 @@ namespace AZ
             return true;
         }
 
-        ShaderCollection::Item::Item(const Data::Asset<ShaderAsset>& shaderAsset, const AZ::Name& shaderTag, ShaderVariantId variantId)
+        ShaderCollection::Item::Item(
+            const Data::Asset<ShaderAsset>& shaderAsset, const AZ::Name& shaderTag, DrawItemType drawItemType, ShaderVariantId variantId)
             : m_renderStatesOverlay(RHI::GetInvalidRenderStates())
             , m_shaderAsset(shaderAsset)
             , m_shaderVariantId(variantId)
             , m_shaderTag(shaderTag)
+            , m_drawItemType(drawItemType)
             , m_shaderOptionGroup(shaderAsset->GetShaderOptionGroupLayout(), variantId)
         {
         }
 
-        ShaderCollection::Item::Item(Data::Asset<ShaderAsset>&& shaderAsset, const AZ::Name& shaderTag, ShaderVariantId variantId)
+        ShaderCollection::Item::Item(
+            Data::Asset<ShaderAsset>&& shaderAsset, const AZ::Name& shaderTag, DrawItemType drawItemType, ShaderVariantId variantId)
             : m_renderStatesOverlay(RHI::GetInvalidRenderStates())
             , m_shaderAsset(AZStd::move(shaderAsset))
             , m_shaderVariantId(variantId)
             , m_shaderTag(shaderTag)
+            , m_drawItemType(drawItemType)
             , m_shaderOptionGroup(shaderAsset->GetShaderOptionGroupLayout(), variantId)
         {
         }

+ 18 - 3
Gems/Atom/RPI/Code/Tests/Material/LuaMaterialFunctorTests.cpp

@@ -255,7 +255,12 @@ namespace UnitTest
 
             MaterialTypeAssetCreator materialTypeCreator;
             materialTypeCreator.Begin(Uuid::CreateRandom());
-            materialTypeCreator.AddShader(CreateTestShaderAsset(Uuid::CreateRandom()), AZ::RPI::ShaderVariantId{}, Name{"TestShader"}, materialPipelineName);
+            materialTypeCreator.AddShader(
+                CreateTestShaderAsset(Uuid::CreateRandom()),
+                AZ::RPI::ShaderVariantId{},
+                Name{ "TestShader" },
+                MaterialTypeAssetCreator::DrawItemType::Raster,
+                materialPipelineName);
             materialTypeCreator.BeginMaterialProperty(Name{pipelineMaterialPropertyName}, dataType, materialPipelineName);
             materialTypeCreator.EndMaterialProperty();
             materialTypeCreator.BeginMaterialProperty(Name{materialPropertyName}, dataType);
@@ -287,7 +292,12 @@ namespace UnitTest
 
             MaterialTypeAssetCreator materialTypeCreator;
             materialTypeCreator.Begin(Uuid::CreateRandom());
-            materialTypeCreator.AddShader(CreateTestShaderAsset(Uuid::CreateRandom(), {}, shaderOptionsLayout), AZ::RPI::ShaderVariantId{}, Name{"TestShader"}, materialPipelineName);
+            materialTypeCreator.AddShader(
+                CreateTestShaderAsset(Uuid::CreateRandom(), {}, shaderOptionsLayout),
+                AZ::RPI::ShaderVariantId{},
+                Name{ "TestShader" },
+                MaterialTypeAssetCreator::DrawItemType::Raster,
+                materialPipelineName);
             materialTypeCreator.BeginMaterialProperty(Name{pipelineMaterialPropertyName}, dataType, materialPipelineName);
             materialTypeCreator.EndMaterialProperty();
             materialTypeCreator.BeginMaterialProperty(Name{materialPropertyName}, dataType);
@@ -320,7 +330,12 @@ namespace UnitTest
 
             MaterialTypeAssetCreator materialTypeCreator;
             materialTypeCreator.Begin(Uuid::CreateRandom());
-            materialTypeCreator.AddShader(CreateTestShaderAsset(Uuid::CreateRandom()), AZ::RPI::ShaderVariantId{}, Name{"TestShader"}, materialPipelineName);
+            materialTypeCreator.AddShader(
+                CreateTestShaderAsset(Uuid::CreateRandom()),
+                AZ::RPI::ShaderVariantId{},
+                Name{ "TestShader" },
+                MaterialTypeAssetCreator::DrawItemType::Raster,
+                materialPipelineName);
             materialTypeCreator.BeginMaterialProperty(Name{pipelineMaterialPropertyName}, pipelineMaterialPropertyType, materialPipelineName);
             materialTypeCreator.EndMaterialProperty();
             materialTypeCreator.BeginMaterialProperty(Name{materialPropertyName}, materialPropertyType);

+ 31 - 24
Gems/Atom/RPI/Code/Tests/Material/MaterialTests.cpp

@@ -865,14 +865,15 @@ namespace UnitTest
         //               "peculiar"
         //               "shaderB"
 
+        using DrawItemType = MaterialTypeAssetCreator::DrawItemType;
         MaterialTypeAssetCreator materialTypeCreator;
         materialTypeCreator.Begin(Uuid::CreateRandom());
-        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"shader1"}, Name{"PipalineA"});
-        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"shader2"}, Name{"PipalineA"});
-        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"special"}, Name{"PipalineA"});
-        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"shaderA"}, Name{"PipalineB"});
-        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"peculiar"}, Name{"PipalineB"});
-        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"shaderB"}, Name{"PipalineB"});
+        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"shader1"}, DrawItemType::Raster, Name{"PipalineA"});
+        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"shader2"}, DrawItemType::Raster, Name{"PipalineA"});
+        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"special"}, DrawItemType::Raster, Name{"PipalineA"});
+        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"shaderA"}, DrawItemType::Raster, Name{"PipalineB"});
+        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"peculiar"}, DrawItemType::Raster, Name{"PipalineB"});
+        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"shaderB"}, DrawItemType::Raster, Name{"PipalineB"});
         materialTypeCreator.SetMaterialShaderParameterLayout(m_testMaterialShaderParameterLayout);
 
         // PipalineA's EnableSpecialFeature connects to its "special" shader
@@ -964,15 +965,17 @@ namespace UnitTest
         //               "shaderA"
         //               "peculiar"
         //               "shaderB"
+        
+        using DrawItemType = MaterialTypeAssetCreator::DrawItemType;
 
         MaterialTypeAssetCreator materialTypeCreator;
         materialTypeCreator.Begin(Uuid::CreateRandom());
-        materialTypeCreator.AddShader(m_testMaterialShaderAsset, ShaderVariantId{}, Name{"shader1"}, Name{"PipalineA"});
-        materialTypeCreator.AddShader(m_testMaterialShaderAsset, ShaderVariantId{}, Name{"shader2"}, Name{"PipalineA"});
-        materialTypeCreator.AddShader(m_testMaterialShaderAsset, ShaderVariantId{}, Name{"special"}, Name{"PipalineA"});
-        materialTypeCreator.AddShader(m_testMaterialShaderAsset, ShaderVariantId{}, Name{"shaderA"}, Name{"PipalineB"});
-        materialTypeCreator.AddShader(m_testMaterialShaderAsset, ShaderVariantId{}, Name{"peculiar"}, Name{"PipalineB"});
-        materialTypeCreator.AddShader(m_testMaterialShaderAsset, ShaderVariantId{}, Name{"shaderB"}, Name{"PipalineB"});
+        materialTypeCreator.AddShader(m_testMaterialShaderAsset, ShaderVariantId{}, Name{"shader1"}, DrawItemType::Raster, Name{"PipalineA"});
+        materialTypeCreator.AddShader(m_testMaterialShaderAsset, ShaderVariantId{}, Name{"shader2"}, DrawItemType::Raster, Name{"PipalineA"});
+        materialTypeCreator.AddShader(m_testMaterialShaderAsset, ShaderVariantId{}, Name{"special"}, DrawItemType::Raster, Name{"PipalineA"});
+        materialTypeCreator.AddShader(m_testMaterialShaderAsset, ShaderVariantId{}, Name{"shaderA"}, DrawItemType::Raster, Name{"PipalineB"});
+        materialTypeCreator.AddShader(m_testMaterialShaderAsset, ShaderVariantId{}, Name{"peculiar"}, DrawItemType::Raster, Name{"PipalineB"});
+        materialTypeCreator.AddShader(m_testMaterialShaderAsset, ShaderVariantId{}, Name{"shaderB"}, DrawItemType::Raster, Name{"PipalineB"});
         materialTypeCreator.SetMaterialShaderParameterLayout(m_testMaterialShaderParameterLayout);
 
         // PipalineA's EnableSpecialFeature connects to its "special" shader
@@ -1073,14 +1076,16 @@ namespace UnitTest
         //           Functors
         //               ShaderEnablePipelineFunctor uses "EnableSpecialFeature" to enable/disable the "peculiar" shader
         
+        using DrawItemType = MaterialTypeAssetCreator::DrawItemType;
+
         MaterialTypeAssetCreator materialTypeCreator;
         materialTypeCreator.Begin(Uuid::CreateRandom());
-        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"shader1"}, Name{"PipalineA"});
-        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"shader2"}, Name{"PipalineA"});
-        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"special"}, Name{"PipalineA"});
-        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"shaderA"}, Name{"PipalineB"});
-        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"peculiar"}, Name{"PipalineB"});
-        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"shaderB"}, Name{"PipalineB"});
+        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"shader1"}, DrawItemType::Raster, Name{"PipalineA"});
+        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"shader2"}, DrawItemType::Raster, Name{"PipalineA"});
+        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"special"}, DrawItemType::Raster, Name{"PipalineA"});
+        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"shaderA"}, DrawItemType::Raster, Name{"PipalineB"});
+        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"peculiar"}, DrawItemType::Raster, Name{"PipalineB"});
+        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"shaderB"}, DrawItemType::Raster, Name{"PipalineB"});
         materialTypeCreator.SetMaterialShaderParameterLayout(m_testMaterialShaderParameterLayout);
 
         // PipalineA's EnableSpecialFeature connects to its "special" shader
@@ -1190,14 +1195,16 @@ namespace UnitTest
         //           Functors
         //               ShaderEnablePipelineFunctor uses "EnableSpecialFeature" to enable/disable the "peculiar" shader
 
+        using DrawItemType = MaterialTypeAssetCreator::DrawItemType;
+
         MaterialTypeAssetCreator materialTypeCreator;
         materialTypeCreator.Begin(Uuid::CreateRandom());
-        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"shader1"}, Name{"PipalineA"});
-        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"shader2"}, Name{"PipalineA"});
-        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"special"}, Name{"PipalineA"});
-        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"shaderA"}, Name{"PipalineB"});
-        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"peculiar"}, Name{"PipalineB"});
-        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"shaderB"}, Name{"PipalineB"});
+        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"shader1"}, DrawItemType::Raster, Name{"PipalineA"});
+        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"shader2"}, DrawItemType::Raster, Name{"PipalineA"});
+        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"special"}, DrawItemType::Raster, Name{"PipalineA"});
+        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"shaderA"}, DrawItemType::Raster, Name{"PipalineB"});
+        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"peculiar"}, DrawItemType::Raster, Name{"PipalineB"});
+        materialTypeCreator.AddShader(m_testMaterialShaderAsset, AZ::RPI::ShaderVariantId{}, Name{"shaderB"}, DrawItemType::Raster, Name{"PipalineB"});
         materialTypeCreator.SetMaterialShaderParameterLayout(m_testMaterialShaderParameterLayout);
 
         // PipalineA's EnableSpecialFeature connects to its "special" shader

+ 121 - 45
Gems/Atom/RPI/Code/Tests/Material/MaterialTypeAssetTests.cpp

@@ -957,9 +957,11 @@ namespace UnitTest
         materialTypeCreator.Begin(assetId);
 
         // Include a shader for both MaterialPipelineNone and "TestPipeline" because it doesn't matter where the ShaderResourceGroup
-        // appears, the material pipeline should not have access to it. 
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, MaterialPipelineNone);
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, Name{"TestPipeline"});
+        // appears, the material pipeline should not have access to it.
+        materialTypeCreator.AddShader(
+            m_testShaderAsset, ShaderVariantId{}, Name{}, MaterialTypeAssetCreator::DrawItemType::Raster, MaterialPipelineNone);
+        materialTypeCreator.AddShader(
+            m_testShaderAsset, ShaderVariantId{}, Name{}, MaterialTypeAssetCreator::DrawItemType::Raster, Name{ "TestPipeline" });
 
         materialTypeCreator.BeginMaterialProperty(Name{"materialPipelineBoolProperty"}, MaterialPropertyDataType::Bool, Name{"TestPipeline"});
 
@@ -979,6 +981,7 @@ namespace UnitTest
 
         using namespace AZ;
         using namespace AZ::RPI;
+        using DrawItemType = MaterialTypeAssetCreator::DrawItemType;
 
         Data::Asset<MaterialTypeAsset> materialTypeAsset;
 
@@ -987,12 +990,13 @@ namespace UnitTest
         MaterialTypeAssetCreator materialTypeCreator;
         materialTypeCreator.Begin(assetId);
 
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, MaterialPipelineNone);
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, MaterialPipelineNone);
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, Name{"PipelineA"});
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, Name{"PipelineA"});
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, Name{"PipelineB"});
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, Name{"PipelineB"});
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, DrawItemType::Raster, MaterialPipelineNone);
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, DrawItemType::Raster, MaterialPipelineNone);
+        // Modify the drawItemType to make sure it doesn't interfere
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, DrawItemType::Deferred, Name{ "PipelineA" });
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, DrawItemType::Deferred, Name{ "PipelineA" });
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, DrawItemType::Custom, Name{ "PipelineB" });
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, DrawItemType::Custom, Name{ "PipelineB" });
 
         materialTypeCreator.BeginMaterialProperty(Name{"debug"}, MaterialPropertyDataType::Bool, MaterialPipelineNone);
         materialTypeCreator.ConnectMaterialPropertyToShaderOptions(Name{"o_debug"});
@@ -1022,6 +1026,66 @@ namespace UnitTest
         checkShaderOption(5, Name{"PipelineB"}, 1);
     }
 
+    TEST_F(MaterialTypeAssetTests, MaterialTypeAsset_DrawItemType)
+    {
+        // Normal material property connections to ShaderOption will apply to every shader in the material type,
+        // including any shaders that are inside MaterialPipeline(s).
+
+        using namespace AZ;
+        using namespace AZ::RPI;
+        using DrawItemType = MaterialTypeAssetCreator::DrawItemType;
+
+        Data::Asset<MaterialTypeAsset> materialTypeAsset;
+
+        Data::AssetId assetId(Uuid::CreateRandom());
+
+        MaterialTypeAssetCreator materialTypeCreator;
+        materialTypeCreator.Begin(assetId);
+
+        // Default: DrawItemType::Raster
+        materialTypeCreator.AddShader(m_testShaderAsset);
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, DrawItemType::Deferred, MaterialPipelineNone);
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, DrawItemType::Custom, MaterialPipelineNone);
+
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, DrawItemType::Raster, Name{ "PipelineA" });
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, DrawItemType::Deferred, Name{ "PipelineA" });
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, DrawItemType::Custom, Name{ "PipelineA" });
+
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, DrawItemType::Custom, Name{ "PipelineB" });
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, DrawItemType::Raster, Name{ "PipelineB" });
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, DrawItemType::Deferred, Name{ "PipelineB" });
+
+        materialTypeCreator.End(materialTypeAsset);
+
+        auto checkShaderDrawItemType =
+            [&materialTypeAsset](uint32_t shaderIndex, const Name& pipelineName, const MaterialTypeAssetCreator::DrawItemType drawItemType)
+        {
+            if (pipelineName == MaterialPipelineNone)
+            {
+                auto& shaderCollection = materialTypeAsset->GetGeneralShaderCollection();
+                EXPECT_EQ(shaderCollection[shaderIndex].GetDrawItemType(), drawItemType);
+            }
+            else
+            {
+                auto& pipelinePayload = materialTypeAsset->GetMaterialPipelinePayloads().at(pipelineName);
+                auto& shaderCollection = pipelinePayload.m_shaderCollection;
+                EXPECT_EQ(shaderCollection[shaderIndex].GetDrawItemType(), drawItemType);
+            }
+        };
+
+        checkShaderDrawItemType(0, MaterialPipelineNone, MaterialTypeAssetCreator::DrawItemType::Raster);
+        checkShaderDrawItemType(1, MaterialPipelineNone, MaterialTypeAssetCreator::DrawItemType::Deferred);
+        checkShaderDrawItemType(2, MaterialPipelineNone, MaterialTypeAssetCreator::DrawItemType::Custom);
+
+        checkShaderDrawItemType(0, Name{ "PipelineA" }, MaterialTypeAssetCreator::DrawItemType::Raster);
+        checkShaderDrawItemType(1, Name{ "PipelineA" }, MaterialTypeAssetCreator::DrawItemType::Deferred);
+        checkShaderDrawItemType(2, Name{ "PipelineA" }, MaterialTypeAssetCreator::DrawItemType::Custom);
+
+        checkShaderDrawItemType(0, Name{ "PipelineB" }, MaterialTypeAssetCreator::DrawItemType::Custom);
+        checkShaderDrawItemType(1, Name{ "PipelineB" }, MaterialTypeAssetCreator::DrawItemType::Raster);
+        checkShaderDrawItemType(2, Name{ "PipelineB" }, MaterialTypeAssetCreator::DrawItemType::Deferred);
+    }
+
     TEST_F(MaterialTypeAssetTests, InternalPipelineProperty_ConnectToShaderOption_AccessesLocalShadersOnly)
     {
         // Internal material properties that are part of a material pipeline should only set shader options
@@ -1029,6 +1093,7 @@ namespace UnitTest
 
         using namespace AZ;
         using namespace AZ::RPI;
+        using DrawItemType = MaterialTypeAssetCreator::DrawItemType;
 
         Data::Asset<MaterialTypeAsset> materialTypeAsset;
 
@@ -1037,12 +1102,12 @@ namespace UnitTest
         MaterialTypeAssetCreator materialTypeCreator;
         materialTypeCreator.Begin(assetId);
 
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, MaterialPipelineNone);
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, MaterialPipelineNone);
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, Name{"PipelineA"});
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, Name{"PipelineA"});
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, Name{"PipelineB"});
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, Name{"PipelineB"});
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, DrawItemType::Raster, MaterialPipelineNone);
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, DrawItemType::Raster, MaterialPipelineNone);
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, DrawItemType::Raster, Name{ "PipelineA" });
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, DrawItemType::Raster, Name{ "PipelineA" });
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, DrawItemType::Raster, Name{ "PipelineB" });
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, DrawItemType::Raster, Name{ "PipelineB" });
 
         materialTypeCreator.BeginMaterialProperty(Name{"debug"}, MaterialPropertyDataType::Bool, Name{"PipelineA"});
         materialTypeCreator.ConnectMaterialPropertyToShaderOptions(Name{"o_debug"});
@@ -1077,6 +1142,7 @@ namespace UnitTest
 
         using namespace AZ;
         using namespace AZ::RPI;
+        using DrawItemType = MaterialTypeAssetCreator::DrawItemType;
 
         Data::Asset<MaterialTypeAsset> materialTypeAsset;
 
@@ -1085,12 +1151,12 @@ namespace UnitTest
         MaterialTypeAssetCreator materialTypeCreator;
         materialTypeCreator.Begin(assetId);
 
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{"shaderA"}, MaterialPipelineNone);
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{"shaderB"}, MaterialPipelineNone);
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{"shaderA"}, Name{"PipelineA"});
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{"shaderB"}, Name{"PipelineA"});
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{"shaderA"}, Name{"PipelineB"});
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{"shaderB"}, Name{"PipelineB"});
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{ "shaderA" }, DrawItemType::Raster, MaterialPipelineNone);
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{ "shaderB" }, DrawItemType::Raster, MaterialPipelineNone);
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{ "shaderA" }, DrawItemType::Raster, Name{ "PipelineA" });
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{ "shaderB" }, DrawItemType::Raster, Name{ "PipelineA" });
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{ "shaderA" }, DrawItemType::Raster, Name{ "PipelineB" });
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{ "shaderB" }, DrawItemType::Raster, Name{ "PipelineB" });
 
         materialTypeCreator.BeginMaterialProperty(Name{"enable"}, MaterialPropertyDataType::Bool, MaterialPipelineNone);
         materialTypeCreator.ConnectMaterialPropertyToShaderEnabled(Name{"shaderB"});
@@ -1114,6 +1180,7 @@ namespace UnitTest
 
         using namespace AZ;
         using namespace AZ::RPI;
+        using DrawItemType = MaterialTypeAssetCreator::DrawItemType;
 
         Data::Asset<MaterialTypeAsset> materialTypeAsset;
 
@@ -1122,12 +1189,12 @@ namespace UnitTest
         MaterialTypeAssetCreator materialTypeCreator;
         materialTypeCreator.Begin(assetId);
 
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{"shaderA"}, MaterialPipelineNone);
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{"shaderB"}, MaterialPipelineNone);
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{"shaderA"}, Name{"PipelineA"});
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{"shaderB"}, Name{"PipelineA"});
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{"shaderA"}, Name{"PipelineB"});
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{"shaderB"}, Name{"PipelineB"});
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{ "shaderA" }, DrawItemType::Raster, MaterialPipelineNone);
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{ "shaderB" }, DrawItemType::Raster, MaterialPipelineNone);
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{ "shaderA" }, DrawItemType::Raster, Name{ "PipelineA" });
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{ "shaderB" }, DrawItemType::Raster, Name{ "PipelineA" });
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{ "shaderA" }, DrawItemType::Raster, Name{ "PipelineB" });
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{ "shaderB" }, DrawItemType::Raster, Name{ "PipelineB" });
 
         materialTypeCreator.BeginMaterialProperty(Name{"enable"}, MaterialPropertyDataType::Bool, Name{"PipelineA"});
         materialTypeCreator.ConnectMaterialPropertyToShaderEnabled(Name{"shaderB"});
@@ -1152,6 +1219,7 @@ namespace UnitTest
 
         using namespace AZ;
         using namespace AZ::RPI;
+        using DrawItemType = MaterialTypeAssetCreator::DrawItemType;
 
         Data::Asset<MaterialTypeAsset> materialTypeAsset;
 
@@ -1160,9 +1228,9 @@ namespace UnitTest
         MaterialTypeAssetCreator materialTypeCreator;
         materialTypeCreator.Begin(assetId);
 
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, Name{"PipelineA"});
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, Name{"PipelineB"});
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, Name{"PipelineC"});
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, DrawItemType::Raster, Name{ "PipelineA" });
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, DrawItemType::Raster, Name{ "PipelineB" });
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, DrawItemType::Raster, Name{ "PipelineC" });
 
         // PipelineA properties
         materialTypeCreator.BeginMaterialProperty(Name{"unused1"}, MaterialPropertyDataType::Bool, Name{"PipelineA"});
@@ -1220,6 +1288,7 @@ namespace UnitTest
 
         using namespace AZ;
         using namespace AZ::RPI;
+        using DrawItemType = MaterialTypeAssetCreator::DrawItemType;
 
         Data::Asset<MaterialTypeAsset> materialTypeAsset;
 
@@ -1228,9 +1297,9 @@ namespace UnitTest
         MaterialTypeAssetCreator materialTypeCreator;
         materialTypeCreator.Begin(assetId);
 
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, Name{"PipelineA"});
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, Name{"PipelineB"});
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, Name{"PipelineC"});
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, DrawItemType::Raster, Name{ "PipelineA" });
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, DrawItemType::Raster, Name{ "PipelineB" });
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, DrawItemType::Raster, Name{ "PipelineC" });
 
         // PipelineA property
         materialTypeCreator.BeginMaterialProperty(Name{"castShadows"}, MaterialPropertyDataType::Bool, Name{"PipelineA"});
@@ -1251,6 +1320,7 @@ namespace UnitTest
     {
         using namespace AZ;
         using namespace AZ::RPI;
+        using DrawItemType = MaterialTypeAssetCreator::DrawItemType;
 
         Data::Asset<MaterialTypeAsset> materialTypeAsset;
 
@@ -1259,7 +1329,7 @@ namespace UnitTest
         MaterialTypeAssetCreator materialTypeCreator;
         materialTypeCreator.Begin(assetId);
 
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, Name{"PipelineA"});
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, DrawItemType::Raster, Name{ "PipelineA" });
 
         // PipelineA property is a int
         materialTypeCreator.BeginMaterialProperty(Name{"someInt"}, MaterialPropertyDataType::UInt, Name{"PipelineA"});
@@ -1280,6 +1350,7 @@ namespace UnitTest
     {
         using namespace AZ;
         using namespace AZ::RPI;
+        using DrawItemType = MaterialTypeAssetCreator::DrawItemType;
 
         Data::Asset<MaterialTypeAsset> materialTypeAsset;
 
@@ -1288,7 +1359,7 @@ namespace UnitTest
         MaterialTypeAssetCreator materialTypeCreator;
         materialTypeCreator.Begin(assetId);
 
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, Name{"PipelineA"});
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{}, DrawItemType::Raster, Name{ "PipelineA" });
 
         // PipelineA property
         materialTypeCreator.BeginMaterialProperty(Name{"enableSomething"}, MaterialPropertyDataType::Bool, MaterialPipelineNone);
@@ -1309,6 +1380,7 @@ namespace UnitTest
     {
         using namespace AZ;
         using namespace AZ::RPI;
+        using DrawItemType = MaterialTypeAssetCreator::DrawItemType;
 
         Data::Asset<MaterialTypeAsset> materialTypeAsset;
 
@@ -1344,14 +1416,20 @@ namespace UnitTest
 
         // Note we just use the same shader asset repeatedly for simplicity, not realism.
 
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{"depth"}, Name{"MainPipeline"});
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{"shadows"}, Name{"MainPipeline"});
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{"forward"}, Name{"MainPipeline"});
+        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{ "depth" }, DrawItemType::Raster, Name{ "MainPipeline" });
+        materialTypeCreator.AddShader(
+            m_testShaderAsset, ShaderVariantId{}, Name{ "shadows" }, DrawItemType::Raster, Name{ "MainPipeline" });
+        materialTypeCreator.AddShader(
+            m_testShaderAsset, ShaderVariantId{}, Name{ "forward" }, DrawItemType::Raster, Name{ "MainPipeline" });
 
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{"shadows"}, Name{"DeferredPipeline"});
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{"deferred"}, Name{"DeferredPipeline"});
+        // Set the DrawItemType to deferred, to make sure it doesn't interfere with anything else
+        materialTypeCreator.AddShader(
+            m_testShaderAsset, ShaderVariantId{}, Name{ "shadows" }, DrawItemType::Deferred, Name{ "DeferredPipeline" });
+        materialTypeCreator.AddShader(
+            m_testShaderAsset, ShaderVariantId{}, Name{ "deferred" }, DrawItemType::Deferred, Name{ "DeferredPipeline" });
 
-        materialTypeCreator.AddShader(m_testShaderAsset, ShaderVariantId{}, Name{"forward"}, Name{"LowEndPipeline"});
+        materialTypeCreator.AddShader(
+            m_testShaderAsset, ShaderVariantId{}, Name{ "forward" }, DrawItemType::Raster, Name{ "LowEndPipeline" });
 
         // This internal property enables the shadow shader via direct connection
         materialTypeCreator.BeginMaterialProperty(Name{"castShadows"}, MaterialPropertyDataType::Bool, Name{"MainPipeline"});
@@ -2268,11 +2346,9 @@ namespace UnitTest
         creator.AddShader(m_testShaderAsset);
         creator.BeginMaterialProperty(Name{"bool"}, MaterialPropertyDataType::Bool);
 
-        AZ_TEST_START_ASSERTTEST;
-        creator.ConnectMaterialPropertyToShaderOptions(Name{"DoesNotExist"});
-        AZ_TEST_STOP_ASSERTTEST(1);
+        creator.ConnectMaterialPropertyToShaderOptions(Name{ "DoesNotExist" });
 
-        EXPECT_EQ(1, creator.GetErrorCount());
+        EXPECT_EQ(1, creator.GetWarningCount());
     }
 
     TEST_F(MaterialTypeAssetTests, ShaderOptionOwnership)

+ 3 - 4
Gems/Atom/RPI/Code/Tests/Material/MaterialTypeSourceDataTests.cpp

@@ -1092,10 +1092,9 @@ namespace UnitTest
         MaterialPropertySourceData* property = propertyGroup->AddProperty("MyInt");
         property->m_dataType = MaterialPropertyDataType::Int;
         property->m_outputConnections.push_back(MaterialPropertySourceData::Connection{MaterialPropertyOutputType::ShaderOption, AZStd::string("DoesNotExist")});
-        
-        AZ_TEST_START_TRACE_SUPPRESSION;
-        auto materialTypeOutcome = sourceData.CreateMaterialTypeAsset(Uuid::CreateRandom());
-        AZ_TEST_STOP_TRACE_SUPPRESSION(2); // There happens to be an extra assert for "Cannot continue building MaterialAsset because 1 error(s) reported"
+
+        // elevate warnings to errors
+        auto materialTypeOutcome = sourceData.CreateMaterialTypeAsset(Uuid::CreateRandom(), "", true);
 
         EXPECT_FALSE(materialTypeOutcome.IsSuccess());
     }

+ 1 - 1
Gems/Terrain/Code/Source/TerrainRenderer/TerrainMeshManager.cpp

@@ -580,7 +580,7 @@ namespace Terrain
         m_materialInstance->ForAllShaderItems(
             [&](const AZ::Name& materialPipelineName, const AZ::RPI::ShaderCollection::Item& shaderItem)
             {
-                if (!shaderItem.IsEnabled())
+                if (!shaderItem.IsEnabled() || shaderItem.GetDrawItemType() != AZ::RPI::ShaderCollection::Item::DrawItemType::Raster)
                 {
                     return true;
                 }