Applications like dali-demo end up hashing around 1MB of shader source on startup
due to multiple calls to ShaderFactory::Load ( 340 calls for dali-demo).
The previous code would:
- Allocate a new string to hold both vertex/ fragment source code
- Copy vertex / fragment source code in to the new string
- Pass through the string removing white spaces
- Pass through the string removing tabs
- Pass through the string removing new line characters
- Pass through the string to perform Hash calculation
So if a total of 1MB is passed to the hasher it would end
read/ writing around 5MB of data.
Hence OProfile flagged it up as being a bottleneck for some apps on startup.
New version does no memory allocation and does a single pass of the data.
Todo: Need to look at a better way of comparing shaders
Change-Id: I39c8b351c65c6e91f2c4b32e321f861d634ccca4
namespace Dali
{
+namespace //un-named namespace
+{
/*
* djb2 (http://www.cse.yorku.ca/~oz/hash.html)
*/
-unsigned long StringHash::operator()(const std::string& toHash)
-{
- unsigned long hash = 5381;
+const unsigned long INITIAL_HASH_VALUE = 5381;
- const char *str = toHash.c_str();
-
- while( int c = *str++ )
+inline void HashShader( const char* string, unsigned long& hash )
+{
+ while( int c = *string++ )
{
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
}
+}
+} // un-named namespace
+
+unsigned long CalculateHash(const std::string& toHash)
+{
+ unsigned long hash = INITIAL_HASH_VALUE;
+
+ HashShader( toHash.c_str(), hash );
return hash;
}
+unsigned long CalculateHash(const std::string& string1, const std::string& string2)
+{
+ unsigned long hash = INITIAL_HASH_VALUE;
+
+ HashShader( string1.c_str(), hash);
+ HashShader( string2.c_str(), hash );
+ return hash;
+}
+
+
+
+
} // namespace Dali
namespace Dali
{
-struct StringHash
-{
- unsigned long operator()(const std::string& toHash);
-};
+
+/**
+ * @brief Create a hash code for the string
+ * @param toHash string to hash
+ * @return hash code
+ */
+unsigned long CalculateHash(const std::string& toHash);
+
+
+/**
+ * @brief Create a hash code for 2 strings combined
+ * @param string1 first string
+ * @param string2 second string
+ * @return hash code
+ */
+unsigned long CalculateHash(const std::string& string1, const std::string& string2);
+
+
+
} // namespace Dali
{
ResourceTicketPtr ticket;
- shaderHash = HashShaderSource(vertexSource, fragmentSource);
+ shaderHash = CalculateHash(vertexSource, fragmentSource);
std::stringstream stringHash;
stringHash << shaderHash;
std::string filename = DALI_SHADERBIN_DIR;
}
-size_t ShaderFactory::HashShaderSource(const std::string& vertexSource, const std::string& fragmentSource) const
-{
- std::string source = vertexSource + fragmentSource;
-
- // remove all white spaces, tabs and new lines
- source.erase(std::remove(source.begin(), source.end(), ' '), source.end());
- source.erase(std::remove(source.begin(), source.end(), '\n'), source.end());
- source.erase(std::remove(source.begin(), source.end(), '\t'), source.end());
-
- StringHash hasher;
- return hasher( source );
-}
-
} // namespace Internal
} // namespace Dali
// Undefined
ShaderFactory& operator=( const ShaderFactory& rhs );
- /**
- * Returns a hash of the shader strings
- * @param[in] vertexShaderSrc Source code for the vertex shader
- * @param[in] fragmentShaderSrc Source code for the fragment shader
- * @return Hashed value
- */
- size_t HashShaderSource( const std::string& vertexShaderSrc, const std::string& fragmentShaderSrc ) const;
-
private:
ResourceClient& mResourceClient;
ResourceTypePathIdMap mResourceTypePathIdMap; ///< A map of resource IDs sorted by ResourceTypePath
{
// check url cache
// check if same request exists
- StringHash stringHashFunc;
- std::size_t urlHash = stringHashFunc( filename );
+ std::size_t urlHash = CalculateHash( filename );
Request* foundReq( NULL );
foundReq = FindRequest(filename, urlHash, attr);
#include <dali/internal/event/text/atlas/glyph-atlas-manager.h>
#include <dali/internal/common/dali-hash.h>
-// EXTERNAL INCLUDES
-#include <boost/functional/hash.hpp>
using namespace Dali::Integration;
FontMetricsIntrusivePtr FontFactory::GetFontMetrics( const std::string& fontFamily, const std::string& fontStyle )
{
- StringHash hasher;
- std::size_t hashValue = hasher(fontFamily + fontStyle);
+ std::size_t hashValue = CalculateHash(fontFamily,fontStyle);
FontMetricsIntrusivePtr metrics;
FontMetricsIter iter = mMetricsCache.find( hashValue );
void FontFactory::RemoveFontMetrics(const std::string& fontFamily,
const std::string& fontStyle)
{
- StringHash hasher;
- std::size_t hashValue = hasher(fontFamily + fontStyle);
+ std::size_t hashValue = CalculateHash(fontFamily, fontStyle);
FontMetricsIntrusivePtr metrics;
FontMetricsIter iter = mMetricsCache.find( hashValue );