diff --git a/Source/Engine/Graphics/Shaders/GPUShader.cpp b/Source/Engine/Graphics/Shaders/GPUShader.cpp
index 577452a5c..3fcde42cf 100644
--- a/Source/Engine/Graphics/Shaders/GPUShader.cpp
+++ b/Source/Engine/Graphics/Shaders/GPUShader.cpp
@@ -7,53 +7,7 @@
#include "Engine/Graphics/GPUDevice.h"
#include "Engine/Serialization/MemoryReadStream.h"
-GPUShaderProgramsContainer::GPUShaderProgramsContainer()
- : _shaders(64)
-{
- // TODO: test different values for _shaders capacity, test performance impact (less hash collisions but more memory?)
-}
-
-GPUShaderProgramsContainer::~GPUShaderProgramsContainer()
-{
- // Remember to delete all programs
- _shaders.ClearDelete();
-}
-
-void GPUShaderProgramsContainer::Add(GPUShaderProgram* shader, int32 permutationIndex)
-{
- // Validate input
- ASSERT(shader && Math::IsInRange(permutationIndex, 0, SHADER_PERMUTATIONS_MAX_COUNT - 1));
-#if ENABLE_ASSERTION
- if ((Get(shader->GetName(), permutationIndex) != nullptr))
- {
- CRASH;
- }
-#endif
-
- // Store shader
- const int32 hash = CalculateHash(shader->GetName(), permutationIndex);
- _shaders.Add(hash, shader);
-}
-
-GPUShaderProgram* GPUShaderProgramsContainer::Get(const StringAnsiView& name, int32 permutationIndex) const
-{
- // Validate input
- ASSERT(name.Length() > 0 && Math::IsInRange(permutationIndex, 0, SHADER_PERMUTATIONS_MAX_COUNT - 1));
-
- // Find shader
- GPUShaderProgram* result = nullptr;
- const int32 hash = CalculateHash(name, permutationIndex);
- _shaders.TryGet(hash, result);
-
- return result;
-}
-
-void GPUShaderProgramsContainer::Clear()
-{
- _shaders.ClearDelete();
-}
-
-uint32 GPUShaderProgramsContainer::CalculateHash(const StringAnsiView& name, int32 permutationIndex)
+static FORCE_INLINE uint32 HashPermutation(const StringAnsiView& name, int32 permutationIndex)
{
return GetHash(name) * 37 + permutationIndex;
}
@@ -73,7 +27,7 @@ bool GPUShader::Create(MemoryReadStream& stream)
stream.ReadInt32(&version);
if (version != GPU_SHADER_CACHE_VERSION)
{
- LOG(Warning, "Unsupported shader version {0}. The supported version is {1}.", version, GPU_SHADER_CACHE_VERSION);
+ LOG(Warning, "Unsupported shader version {0}. The current version is {1}.", version, GPU_SHADER_CACHE_VERSION);
return true;
}
@@ -130,19 +84,21 @@ bool GPUShader::Create(MemoryReadStream& stream)
if (shader == nullptr)
{
#if !GPU_ALLOW_TESSELLATION_SHADERS
- if (type == ShaderStage::Hull || type == ShaderStage::Domain)
- continue;
+ if (type == ShaderStage::Hull || type == ShaderStage::Domain)
+ continue;
#endif
#if !GPU_ALLOW_GEOMETRY_SHADERS
- if (type == ShaderStage::Geometry)
- continue;
+ if (type == ShaderStage::Geometry)
+ continue;
#endif
LOG(Error, "Failed to create {} Shader program '{}' ({}).", ::ToString(type), String(initializer.Name), name);
return true;
}
- // Add to collection
- _shaders.Add(shader, permutationIndex);
+ // Add to the collection
+ const uint32 hash = HashPermutation(shader->GetName(), permutationIndex);
+ ASSERT_LOW_LAYER(!_shaders.ContainsKey(hash));
+ _shaders.Add(hash, shader);
}
}
@@ -183,17 +139,21 @@ bool GPUShader::Create(MemoryReadStream& stream)
return false;
}
+bool GPUShader::HasShader(const StringAnsiView& name, int32 permutationIndex) const
+{
+ const uint32 hash = HashPermutation(name, permutationIndex);
+ return _shaders.ContainsKey(hash);
+}
+
GPUShaderProgram* GPUShader::GetShader(ShaderStage stage, const StringAnsiView& name, int32 permutationIndex) const
{
- const auto shader = _shaders.Get(name, permutationIndex);
-
+ GPUShaderProgram* shader = nullptr;
+ const uint32 hash = HashPermutation(name, permutationIndex);
+ _shaders.TryGet(hash, shader);
#if BUILD_RELEASE
-
// Release build is more critical on that
ASSERT(shader != nullptr && shader->GetStage() == stage);
-
#else
-
if (shader == nullptr)
{
LOG(Error, "Missing {0} shader \'{1}\'[{2}]. Object: {3}.", ::ToString(stage), String(name), permutationIndex, ToString());
@@ -202,9 +162,7 @@ GPUShaderProgram* GPUShader::GetShader(ShaderStage stage, const StringAnsiView&
{
LOG(Error, "Invalid shader stage \'{1}\'[{2}]. Expected: {0}. Actual: {4}. Object: {3}.", ::ToString(stage), String(name), permutationIndex, ToString(), ::ToString(shader->GetStage()));
}
-
#endif
-
return shader;
}
@@ -224,5 +182,5 @@ void GPUShader::OnReleaseGPU()
}
}
_memoryUsage = 0;
- _shaders.Clear();
+ _shaders.ClearDelete();
}
diff --git a/Source/Engine/Graphics/Shaders/GPUShader.h b/Source/Engine/Graphics/Shaders/GPUShader.h
index c48bf48b3..0ff511cc3 100644
--- a/Source/Engine/Graphics/Shaders/GPUShader.h
+++ b/Source/Engine/Graphics/Shaders/GPUShader.h
@@ -14,64 +14,15 @@ class GPUShaderProgram;
///
#define GPU_SHADER_CACHE_VERSION 9
-///
-/// Represents collection of shader programs with permutations and custom names.
-///
-class GPUShaderProgramsContainer
-{
-private:
- Dictionary _shaders;
-
-public:
- ///
- /// Initializes a new instance of the class.
- ///
- GPUShaderProgramsContainer();
-
- ///
- /// Finalizes an instance of the class.
- ///
- ~GPUShaderProgramsContainer();
-
-public:
- ///
- /// Adds a new shader program to the collection.
- ///
- /// The shader to store.
- /// The shader permutation index.
- void Add(GPUShaderProgram* shader, int32 permutationIndex);
-
- ///
- /// Gets a shader of given name and permutation index.
- ///
- /// The shader program name.
- /// The shader permutation index.
- /// Stored shader program or null if cannot find it.
- GPUShaderProgram* Get(const StringAnsiView& name, int32 permutationIndex) const;
-
- ///
- /// Clears collection (deletes all shaders).
- ///
- void Clear();
-
-public:
- ///
- /// Calculates unique hash for given shader program name and its permutation index.
- ///
- /// The shader program name.
- /// The shader program permutation index.
- /// Calculated hash value.
- static uint32 CalculateHash(const StringAnsiView& name, int32 permutationIndex);
-};
-
///
/// The GPU resource with shader programs that can run on the GPU and are able to perform rendering calculation using textures, vertices and other resources.
///
API_CLASS(Sealed, NoSpawn) class FLAXENGINE_API GPUShader : public GPUResource
{
DECLARE_SCRIPTING_TYPE_NO_SPAWN(GPUShader);
+
protected:
- GPUShaderProgramsContainer _shaders;
+ Dictionary _shaders;
GPUConstantBuffer* _constantBuffers[MAX_CONSTANT_BUFFER_SLOTS];
GPUShader();
@@ -173,17 +124,13 @@ public:
return _constantBuffers[slot];
}
-public:
///
/// Determines whether the specified shader program is in the shader.
///
/// The shader program name.
/// The shader permutation index.
/// true if the shader is valid; otherwise, false.
- FORCE_INLINE bool HasShader(const StringAnsiView& name, int32 permutationIndex = 0) const
- {
- return _shaders.Get(name, permutationIndex) != nullptr;
- }
+ bool HasShader(const StringAnsiView& name, int32 permutationIndex = 0) const;
protected:
GPUShaderProgram* GetShader(ShaderStage stage, const StringAnsiView& name, int32 permutationIndex) const;