diff --git a/Source/Engine/Content/Assets/Material.cpp b/Source/Engine/Content/Assets/Material.cpp
index 79b7352cd..3042f66da 100644
--- a/Source/Engine/Content/Assets/Material.cpp
+++ b/Source/Engine/Content/Assets/Material.cpp
@@ -467,10 +467,6 @@ void Material::OnDependencyModified(BinaryAsset* asset)
Reload();
}
-#endif
-
-#if USE_EDITOR
-
void Material::InitCompilationOptions(ShaderCompilationOptions& options)
{
// Base
@@ -488,7 +484,7 @@ void Material::InitCompilationOptions(ShaderCompilationOptions& options)
const bool useForward = ((info.Domain == MaterialDomain::Surface || info.Domain == MaterialDomain::Deformable) && !isOpaque) || info.Domain == MaterialDomain::Particle;
const bool useTess =
info.TessellationMode != TessellationMethod::None &&
- RenderTools::CanSupportTessellation(options.Profile) && isSurfaceOrTerrainOrDeformable;
+ EnumHasAllFlags(RenderTools::GetShaderProfileFeatures(options.Profile), ShaderProfileFeatures::TessellationShaders) && isSurfaceOrTerrainOrDeformable;
const bool useDistortion =
(info.Domain == MaterialDomain::Surface || info.Domain == MaterialDomain::Deformable || info.Domain == MaterialDomain::Particle) &&
!isOpaque &&
diff --git a/Source/Engine/Graphics/Enums.h b/Source/Engine/Graphics/Enums.h
index b45ebdf32..0e174c67e 100644
--- a/Source/Engine/Graphics/Enums.h
+++ b/Source/Engine/Graphics/Enums.h
@@ -147,6 +147,37 @@ API_ENUM() enum class ShaderProfile
const Char* ToString(ShaderProfile value);
+///
+/// Shader profile feature flags. Defines a set of features supported by a shader profile.
+///
+API_ENUM() enum class ShaderProfileFeatures
+{
+ ///
+ /// Nothing.
+ ///
+ None = 0,
+
+ ///
+ /// Compute shaders are supported.
+ ///
+ ComputeShaders = 1,
+
+ ///
+ /// Geometry shaders are supported.
+ ///
+ GeometryShaders = 2,
+
+ ///
+ /// Tessellation shaders are supported (Hull and Domain).
+ ///
+ TessellationShaders = 4,
+
+ API_ENUM(Attributes = "HideInEditor")
+ MAX
+};
+
+DECLARE_ENUM_OPERATORS(ShaderProfileFeatures);
+
///
/// Graphics feature levels indicates what level of support can be relied upon.
/// They are named after the graphics API to indicate the minimum level of the features set to support.
diff --git a/Source/Engine/Graphics/RenderTools.cpp b/Source/Engine/Graphics/RenderTools.cpp
index 0d10380a2..d658b902c 100644
--- a/Source/Engine/Graphics/RenderTools.cpp
+++ b/Source/Engine/Graphics/RenderTools.cpp
@@ -9,7 +9,6 @@
#include "RenderTask.h"
#include "Engine/Content/Assets/Model.h"
#include "Engine/Content/Assets/SkinnedModel.h"
-#include "Engine/Core/Log.h"
#include "Engine/Core/Math/Packed.h"
#include "Engine/Core/Math/OrientedBoundingBox.h"
#include "Engine/Engine/Time.h"
@@ -281,6 +280,24 @@ FeatureLevel RenderTools::GetFeatureLevel(ShaderProfile profile)
}
}
+ShaderProfileFeatures RenderTools::GetShaderProfileFeatures(ShaderProfile profile)
+{
+ switch (profile)
+ {
+ case ShaderProfile::DirectX_SM6:
+ case ShaderProfile::DirectX_SM5:
+ case ShaderProfile::Vulkan_SM5:
+ return ShaderProfileFeatures::ComputeShaders | ShaderProfileFeatures::GeometryShaders | ShaderProfileFeatures::TessellationShaders;
+ case ShaderProfile::PS4:
+ case ShaderProfile::PS5:
+ return ShaderProfileFeatures::ComputeShaders | ShaderProfileFeatures::GeometryShaders;
+ case ShaderProfile::DirectX_SM4:
+ return ShaderProfileFeatures::GeometryShaders;
+ default:
+ return ShaderProfileFeatures::None;
+ }
+}
+
bool RenderTools::CanSupportTessellation(ShaderProfile profile)
{
switch (profile)
diff --git a/Source/Engine/Graphics/RenderTools.h b/Source/Engine/Graphics/RenderTools.h
index 2a2bc6357..92790c288 100644
--- a/Source/Engine/Graphics/RenderTools.h
+++ b/Source/Engine/Graphics/RenderTools.h
@@ -47,12 +47,20 @@ public:
/// The feature level matching the given shader profile.
static FeatureLevel GetFeatureLevel(ShaderProfile profile);
+ ///
+ /// Gets the features for the given shader profile. Runtime device might not support all of them.
+ ///
+ /// The shader profile.
+ /// The feature flags for the given shader profile.
+ static ShaderProfileFeatures GetShaderProfileFeatures(ShaderProfile profile);
+
///
/// Check if the given shader profile supports the tessellation. Runtime can reject tessellation support but it defines if given shader profile CAN support tessellation.
+ /// [Deprecated in v1.12]
///
/// The profile.
/// True if can support tessellation shaders, otherwise false.
- static bool CanSupportTessellation(ShaderProfile profile);
+ DEPRECATED("Use GetShaderProfileFeatures instead") static bool CanSupportTessellation(ShaderProfile profile);
///
/// Computes the image row pitch in bytes, and the slice pitch (size in bytes of the image) based on format, width, and height.
diff --git a/Source/Engine/ShadersCompilation/Parser/IShaderParser.h b/Source/Engine/ShadersCompilation/Parser/IShaderParser.h
index 72d4b85d1..8c1f0c81b 100644
--- a/Source/Engine/ShadersCompilation/Parser/IShaderParser.h
+++ b/Source/Engine/ShadersCompilation/Parser/IShaderParser.h
@@ -55,6 +55,12 @@ namespace ShaderProcessing
/// The graphics feature level
virtual FeatureLevel GetFeatureLevel() const = 0;
+ ///
+ /// Gets the parser feature flags for the Shader Profile of the target platform graphics backend.
+ ///
+ /// The shader profile features mask.
+ virtual ShaderProfileFeatures GetFeatures() const = 0;
+
///
/// Gets the parser macros.
///
diff --git a/Source/Engine/ShadersCompilation/Parser/ShaderFunctionReader.h b/Source/Engine/ShadersCompilation/Parser/ShaderFunctionReader.h
index 1727f9f4c..da821b716 100644
--- a/Source/Engine/ShadersCompilation/Parser/ShaderFunctionReader.h
+++ b/Source/Engine/ShadersCompilation/Parser/ShaderFunctionReader.h
@@ -354,10 +354,7 @@ namespace ShaderProcessing
// Clear current meta
auto& current = ShaderMetaReaderType::_current;
- current.Name.Clear();
- current.Permutations.Clear();
- current.Flags = ShaderFlags::Default;
- current.MinFeatureLevel = FeatureLevel::ES2;
+ current = MetaType();
_permutationReader->Clear();
// Here we read '(x, y)\n' where 'x' is a shader function 'visible' flag, and 'y' is mini feature level
@@ -388,6 +385,7 @@ namespace ShaderProcessing
};
MinFeatureLevel levels[] =
{
+ { FeatureLevel::ES2, "AUTO" },
{ FeatureLevel::ES2, "FEATURE_LEVEL_ES2" },
{ FeatureLevel::ES3, "FEATURE_LEVEL_ES3" },
{ FeatureLevel::ES3_1, "FEATURE_LEVEL_ES3_1" },
@@ -406,7 +404,7 @@ namespace ShaderProcessing
}
if (missing)
{
- parser->OnError(TEXT("Invalid shader function \'minFeatureLevel\' option value."));
+ parser->OnError(TEXT("Invalid shader function \'minFeatures\' option value."));
return;
}
@@ -433,7 +431,9 @@ namespace ShaderProcessing
}
// Check if use this shader program
- if ((current.Flags & ShaderFlags::Hidden) == (ShaderFlags)0 && current.MinFeatureLevel <= parser->GetFeatureLevel())
+ if ((current.Flags & ShaderFlags::Hidden) == (ShaderFlags)0 &&
+ current.MinFeatureLevel <= parser->GetFeatureLevel() &&
+ EnumHasAllFlags(parser->GetFeatures(), current.MinFeatures))
{
// Cache read function
ShaderMetaReaderType::_cache.Add(current);
diff --git a/Source/Engine/ShadersCompilation/Parser/ShaderMeta.h b/Source/Engine/ShadersCompilation/Parser/ShaderMeta.h
index c10488812..cb1bcd869 100644
--- a/Source/Engine/ShadersCompilation/Parser/ShaderMeta.h
+++ b/Source/Engine/ShadersCompilation/Parser/ShaderMeta.h
@@ -44,12 +44,17 @@ public:
///
/// Function flags.
///
- ShaderFlags Flags;
+ ShaderFlags Flags = ShaderFlags::Default;
///
- /// The minimum graphics platform feature level to support this shader.
+ /// The minimum graphics platform feature level to support for this shader.
///
- FeatureLevel MinFeatureLevel;
+ FeatureLevel MinFeatureLevel = FeatureLevel::ES2;
+
+ ///
+ /// The minimum shader profile feature to support for this shader.
+ ///
+ ShaderProfileFeatures MinFeatures = ShaderProfileFeatures::None;
///
/// All possible values for the permutations and it's values to generate different permutation of this function
@@ -220,6 +225,11 @@ public:
int32 ControlPointsCount;
public:
+ HullShaderMeta()
+ {
+ MinFeatures = ShaderProfileFeatures::TessellationShaders;
+ }
+
// [ShaderFunctionMeta]
ShaderStage GetStage() const override
{
@@ -233,6 +243,11 @@ public:
class DomainShaderMeta : public ShaderFunctionMeta
{
public:
+ DomainShaderMeta()
+ {
+ MinFeatures = ShaderProfileFeatures::TessellationShaders;
+ }
+
// [ShaderFunctionMeta]
ShaderStage GetStage() const override
{
@@ -246,6 +261,11 @@ public:
class GeometryShaderMeta : public ShaderFunctionMeta
{
public:
+ GeometryShaderMeta()
+ {
+ MinFeatures = ShaderProfileFeatures::GeometryShaders;
+ }
+
// [ShaderFunctionMeta]
ShaderStage GetStage() const override
{
@@ -272,6 +292,11 @@ public:
class ComputeShaderMeta : public ShaderFunctionMeta
{
public:
+ ComputeShaderMeta()
+ {
+ MinFeatures = ShaderProfileFeatures::ComputeShaders;
+ }
+
// [ShaderFunctionMeta]
ShaderStage GetStage() const override
{
diff --git a/Source/Engine/ShadersCompilation/Parser/ShaderProcessing.cpp b/Source/Engine/ShadersCompilation/Parser/ShaderProcessing.cpp
index 3176906ab..7ea79a3b8 100644
--- a/Source/Engine/ShadersCompilation/Parser/ShaderProcessing.cpp
+++ b/Source/Engine/ShadersCompilation/Parser/ShaderProcessing.cpp
@@ -4,10 +4,11 @@
#if COMPILE_WITH_SHADER_COMPILER
+#include "Engine/Core/Log.h"
#include "Engine/Core/Collections/Array.h"
#include "Engine/Utilities/TextProcessing.h"
#include "Engine/Profiler/ProfilerCPU.h"
-#include "Engine/Core/Log.h"
+#include "Engine/Graphics/RenderTools.h"
#include "ShaderFunctionReader.CB.h"
#include "ShaderFunctionReader.VS.h"
#include "ShaderFunctionReader.HS.h"
@@ -17,12 +18,13 @@
#include "ShaderFunctionReader.CS.h"
#include "Config.h"
-ShaderProcessing::Parser::Parser(const String& targetName, const char* source, int32 sourceLength, ParserMacros macros, FeatureLevel featureLevel)
+ShaderProcessing::Parser::Parser(const String& targetName, const char* source, int32 sourceLength, ParserMacros macros, ShaderProfile profile)
: failed(false)
, targetName(targetName)
, text(source, sourceLength)
, _macros(macros)
- , _featureLevel(featureLevel)
+ , _featureLevel(RenderTools::GetFeatureLevel(profile))
+ , _features(RenderTools::GetShaderProfileFeatures(profile))
{
}
@@ -30,10 +32,10 @@ ShaderProcessing::Parser::~Parser()
{
}
-bool ShaderProcessing::Parser::Process(const String& targetName, const char* source, int32 sourceLength, ParserMacros macros, FeatureLevel featureLevel, ShaderMeta* result)
+bool ShaderProcessing::Parser::Process(const String& targetName, const char* source, int32 sourceLength, ParserMacros macros, ShaderProfile profile, ShaderMeta* result)
{
PROFILE_CPU_NAMED("Shader.Parse");
- Parser parser(targetName, source, sourceLength, macros, featureLevel);
+ Parser parser(targetName, source, sourceLength, macros, profile);
parser.Process(result);
return parser.Failed();
}
diff --git a/Source/Engine/ShadersCompilation/Parser/ShaderProcessing.h b/Source/Engine/ShadersCompilation/Parser/ShaderProcessing.h
index 884ff76c1..f0d9afb5f 100644
--- a/Source/Engine/ShadersCompilation/Parser/ShaderProcessing.h
+++ b/Source/Engine/ShadersCompilation/Parser/ShaderProcessing.h
@@ -22,20 +22,18 @@ namespace ShaderProcessing
class Parser : public IShaderParser, public ITokenReadersContainerBase
{
private:
-
bool failed;
String targetName;
Reader text;
ParserMacros _macros;
FeatureLevel _featureLevel;
+ ShaderProfileFeatures _features;
private:
-
- Parser(const String& targetName, const char* source, int32 sourceLength, ParserMacros macros, FeatureLevel featureLevel);
+ Parser(const String& targetName, const char* source, int32 sourceLength, ParserMacros macros, ShaderProfile profile);
~Parser();
public:
-
///
/// Process shader source code and generate metadata
///
@@ -43,13 +41,12 @@ namespace ShaderProcessing
/// ANSI source code
/// Amount of characters in the source code
/// The input macros.
- /// The target feature level.
+ /// The target shader profile.
/// Output result with metadata
/// True if cannot process the file (too many errors), otherwise false
- static bool Process(const String& targetName, const char* source, int32 sourceLength, ParserMacros macros, FeatureLevel featureLevel, ShaderMeta* result);
+ static bool Process(const String& targetName, const char* source, int32 sourceLength, ParserMacros macros, ShaderProfile profile, ShaderMeta* result);
public:
-
///
/// Process shader source code and generate metadata
///
@@ -57,34 +54,32 @@ namespace ShaderProcessing
void Process(ShaderMeta* result);
private:
-
void init();
bool process();
bool collectResults(ShaderMeta* result);
public:
-
// [IShaderParser]
FeatureLevel GetFeatureLevel() const override
{
return _featureLevel;
}
-
+ ShaderProfileFeatures GetFeatures() const override
+ {
+ return _features;
+ }
bool Failed() const override
{
return failed;
}
-
Reader& GetReader() override
{
return text;
}
-
ParserMacros GetMacros() const override
{
return _macros;
}
-
void OnError(const String& message) override;
void OnWarning(const String& message) override;
};
diff --git a/Source/Engine/ShadersCompilation/ShadersCompilation.cpp b/Source/Engine/ShadersCompilation/ShadersCompilation.cpp
index d3e16c98d..c8f68f007 100644
--- a/Source/Engine/ShadersCompilation/ShadersCompilation.cpp
+++ b/Source/Engine/ShadersCompilation/ShadersCompilation.cpp
@@ -152,20 +152,14 @@ bool ShadersCompilation::Compile(ShaderCompilationOptions& options)
options.SourceLength--;
const DateTime startTime = DateTime::NowUTC();
- const FeatureLevel featureLevel = RenderTools::GetFeatureLevel(options.Profile);
// Process shader source to collect metadata
ShaderMeta meta;
- if (ShaderProcessing::Parser::Process(options.TargetName, options.Source, options.SourceLength, options.Macros, featureLevel, &meta))
+ if (ShaderProcessing::Parser::Process(options.TargetName, options.Source, options.SourceLength, options.Macros, options.Profile, &meta))
{
LOG(Warning, "Failed to parse source code.");
return true;
}
- const int32 shadersCount = meta.GetShadersCount();
- if (shadersCount == 0 && featureLevel > FeatureLevel::ES2)
- {
- LOG(Warning, "Shader has no valid functions.");
- }
// Perform actual compilation
bool result;
diff --git a/Source/Engine/Utilities/TextProcessing.cpp b/Source/Engine/Utilities/TextProcessing.cpp
index a78185002..2ac0fc2ad 100644
--- a/Source/Engine/Utilities/TextProcessing.cpp
+++ b/Source/Engine/Utilities/TextProcessing.cpp
@@ -9,8 +9,6 @@ TextProcessing::TextProcessing(const char* input, int32 length)
, _cursor(const_cast(input))
, _position(0)
, _line(1)
- , Separators(32)
- , Whitespaces(8)
{
}
diff --git a/Source/Shaders/Common.hlsl b/Source/Shaders/Common.hlsl
index eaf4793e5..c678259d1 100644
--- a/Source/Shaders/Common.hlsl
+++ b/Source/Shaders/Common.hlsl
@@ -32,14 +32,14 @@
#endif
// Meta macros used by shaders parser
-#define META_VS(isVisible, minFeatureLevel)
+#define META_VS(isVisible, minFeatures)
#define META_VS_IN_ELEMENT(type, index, format, slot, offset, slotClass, stepRate, isVisible) // [Deprecated in v1.10]
-#define META_HS(isVisible, minFeatureLevel)
+#define META_HS(isVisible, minFeatures)
#define META_HS_PATCH(inControlPoints)
-#define META_DS(isVisible, minFeatureLevel)
-#define META_GS(isVisible, minFeatureLevel)
-#define META_PS(isVisible, minFeatureLevel)
-#define META_CS(isVisible, minFeatureLevel)
+#define META_DS(isVisible, minFeatures)
+#define META_GS(isVisible, minFeatures)
+#define META_PS(isVisible, minFeatures)
+#define META_CS(isVisible, minFeatures)
#define META_FLAG(flag)
#define META_PERMUTATION_1(param0)
#define META_PERMUTATION_2(param0, param1)