Previously, all custom Shaders supported file caching, which was not the intended behavior.
therefore, we added a flag to distinguish between internally generated code and externally generated code.
if you want to enable File Caching for externally generated shader code, you can do so using this flag.
(however, the validity of the shader must be verified by the app itself.)
Change-Id: I5e0cb0c6f4177da8159c50e2e27a0833b2c6e54f
Dali::Internal::ThreadLocalStorage& tls = Dali::Internal::ThreadLocalStorage::Get();
Dali::Internal::ShaderFactory& shaderFactory = tls.GetShaderFactory();
size_t shaderHash;
- Internal::ShaderDataPtr shaderData = shaderFactory.Load(vertexShader, fragmentShader, {}, {}, "", shaderHash);
+ Internal::ShaderDataPtr shaderData = shaderFactory.Load(vertexShader, fragmentShader, {}, {}, "", shaderHash, false);
bool dataValid = (shaderData != nullptr);
DALI_TEST_EQUALS(dataValid, true, TEST_LOCATION);
Dali::Internal::ThreadLocalStorage& tls = Dali::Internal::ThreadLocalStorage::Get();
Dali::Internal::ShaderFactory& shaderFactory = tls.GetShaderFactory();
size_t shaderHash;
- Internal::ShaderDataPtr shaderData = shaderFactory.Load(vertexShader, fragmentShader, {}, {}, "", shaderHash);
+ Internal::ShaderDataPtr shaderData = shaderFactory.Load(vertexShader, fragmentShader, {}, {}, "", shaderHash, false);
bool dataValid = (shaderData != nullptr);
DALI_TEST_EQUALS(dataValid, true, TEST_LOCATION);
Dali::Internal::ThreadLocalStorage& tls = Dali::Internal::ThreadLocalStorage::Get();
Dali::Internal::ShaderFactory& shaderFactory = tls.GetShaderFactory();
size_t shaderHash;
- Internal::ShaderDataPtr shaderData = shaderFactory.Load(vertexShader, fragmentShader, {}, {}, "", shaderHash);
+ Internal::ShaderDataPtr shaderData = shaderFactory.Load(vertexShader, fragmentShader, {}, {}, "", shaderHash, false);
bool dataValid = (shaderData != nullptr);
DALI_TEST_EQUALS(dataValid, true, TEST_LOCATION);
tet_printf("Load shader1. It should be fail to load from platform abstraction\n");
size_t shaderHash1 = 0u;
- Internal::ShaderDataPtr shaderData1 = shaderFactory.Load(vertexShader1, fragmentShader1, Shader::Hint::NONE, 0u, "", shaderHash1);
+ Internal::ShaderDataPtr shaderData1 = shaderFactory.Load(vertexShader1, fragmentShader1, Shader::Hint::NONE, 0u, "", shaderHash1, false);
DALI_TEST_CHECK(shaderHash1 != 0u);
DALI_TEST_EQUALS(shaderData1.Get()->HasBinary(), false, TEST_LOCATION);
tet_printf("Load shaderData2 with same code as shaderData1\n");
size_t shaderHash2 = 0u;
- Internal::ShaderDataPtr shaderData2 = shaderFactory.Load(vertexShader1, fragmentShader1, Shader::Hint::NONE, 0u, "", shaderHash2);
+ Internal::ShaderDataPtr shaderData2 = shaderFactory.Load(vertexShader1, fragmentShader1, Shader::Hint::NONE, 0u, "", shaderHash2, false);
tet_printf("Check shaderData2 cached\n");
DALI_TEST_EQUALS(shaderHash2, shaderHash1, TEST_LOCATION);
tet_printf("Load shader3. It will get binary same as dummyBuffer\n");
size_t shaderHash3 = 0u;
- Internal::ShaderDataPtr shaderData3 = shaderFactory.Load(vertexShader2, fragmentShader2, Shader::Hint::NONE, 0u, "", shaderHash3);
+ Internal::ShaderDataPtr shaderData3 = shaderFactory.Load(vertexShader2, fragmentShader2, Shader::Hint::NONE, 0u, "", shaderHash3, false);
DALI_TEST_CHECK(shaderHash3 != 0u);
DALI_TEST_EQUALS(shaderData3.Get()->HasBinary(), true, TEST_LOCATION);
DALI_TEST_EQUALS(shaderData3->GetBufferSize(), dummyBuffer.Count(), TEST_LOCATION);
tet_printf("Load shader1. It should be cached at string container\n");
size_t shaderHash1 = 0u;
- Internal::ShaderDataPtr shaderData1 = shaderFactory.Load(vertexShader1, fragmentShader1, Shader::Hint::NONE, 0u, "", shaderHash1);
+ Internal::ShaderDataPtr shaderData1 = shaderFactory.Load(vertexShader1, fragmentShader1, Shader::Hint::NONE, 0u, "", shaderHash1, false);
DALI_TEST_CHECK(shaderHash1 != 0u);
DALI_TEST_EQUALS(platformAbstraction.WasCalled(TestPlatformAbstraction::SaveShaderBinaryFileFunc), false, TEST_LOCATION);
tet_printf("Load shader2. It also should be cached at string container\n");
size_t shaderHash2 = 0u;
- Internal::ShaderDataPtr shaderData2 = shaderFactory.Load(vertexShader2, fragmentShader2, Shader::Hint::NONE, 0u, "", shaderHash2);
+ Internal::ShaderDataPtr shaderData2 = shaderFactory.Load(vertexShader2, fragmentShader2, Shader::Hint::NONE, 0u, "", shaderHash2, false);
DALI_TEST_CHECK(shaderHash2 != 0u);
DALI_TEST_EQUALS(platformAbstraction.WasCalled(TestPlatformAbstraction::SaveShaderBinaryFileFunc), false, TEST_LOCATION);
tet_printf("Load shader with same code as shaderData1\n");
size_t shaderHash3 = 0u;
- Internal::ShaderDataPtr shaderData3 = shaderFactory.Load(vertexShader1, fragmentShader1, Shader::Hint::NONE, 0u, "", shaderHash3);
+ Internal::ShaderDataPtr shaderData3 = shaderFactory.Load(vertexShader1, fragmentShader1, Shader::Hint::NONE, 0u, "", shaderHash3, false);
tet_printf("Check shaderData1 cached\n");
DALI_TEST_EQUALS(shaderHash3, shaderHash1, TEST_LOCATION);
tet_printf("Load shader with same code as shaderData2\n");
size_t shaderHash4 = 0u;
- Internal::ShaderDataPtr shaderData4 = shaderFactory.Load(vertexShader2, fragmentShader2, Shader::Hint::NONE, 0u, "", shaderHash4);
+ Internal::ShaderDataPtr shaderData4 = shaderFactory.Load(vertexShader2, fragmentShader2, Shader::Hint::NONE, 0u, "", shaderHash4, false);
tet_printf("Check shaderData2 cached\n");
DALI_TEST_EQUALS(shaderHash4, shaderHash2, TEST_LOCATION);
tet_printf("Load shader same as shaderData1, but difference render pass tag\n");
size_t shaderHash5 = 0u;
- Internal::ShaderDataPtr shaderData5 = shaderFactory.Load(vertexShader1, fragmentShader1, Shader::Hint::NONE, 1u, "", shaderHash5);
+ Internal::ShaderDataPtr shaderData5 = shaderFactory.Load(vertexShader1, fragmentShader1, Shader::Hint::NONE, 1u, "", shaderHash5, false);
tet_printf("Check shaderData1 and shaderData5 have same hash, but deferent buffer\n");
DALI_TEST_EQUALS(shaderHash5, shaderHash1, TEST_LOCATION);
return CreateRenderableActor(texture, VERTEX_SHADER, FRAGMENT_SHADER);
}
-Actor CreateRenderableActor(Texture texture, const std::string& vertexShader, const std::string& fragmentShader)
+Actor CreateRenderableActor(Texture texture, const std::string& vertexShader, const std::string& fragmentShader, bool useFileCache)
{
// Create the geometry
Geometry geometry = CreateQuadGeometry();
// Create Shader
- Shader shader = Shader::New(vertexShader, fragmentShader);
+ Shader shader = Shader::New(vertexShader, fragmentShader,Shader::Hint::NONE, "", useFileCache);
// Create renderer from geometry and material
Renderer renderer = Renderer::New(geometry, shader);
* @param[in] texture Texture to set.
* @param[in] vertexShader The vertex-shader.
* @param[in] fragmentShader The fragment-shader.
+ * @param[in] useFileCache If true, the shaders are loaded from files. Otherwise, they are compiled directly. Default is false.
* @return An actor with a renderer.
*/
-Actor CreateRenderableActor(Texture texture, const std::string& vertexShader, const std::string& fragmentShader);
+Actor CreateRenderableActor(Texture texture, const std::string& vertexShader, const std::string& fragmentShader, bool useFileCache = false);
/**
* @brief Creates a renderable-actor with a texture and custom shaders.
inline void GetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary) override
{
+ *length = bufSize; // commonly it is same. so we provide bufSize for test
mGetProgramBinaryCalled = true;
}
return *this;
}
+ /**
+ * @brief Sets whether the program is used the funcation of file-caching by DALi.
+ *
+ * @param[in] value true if the program is used internally by DALi. Otherwise false. Default is false.
+ * @return reference to this structure.
+ */
+ auto& SetFileCaching(bool value)
+ {
+ useFileCache = value;
+ return *this;
+ }
+
GraphicsStructureType type{GraphicsStructureType::PROGRAM_CREATE_INFO_STRUCT};
ExtensionCreateInfo* nextExtension{nullptr};
std::string_view name{};
const std::vector<ShaderState>* shaderState{nullptr};
const AllocationCallbacks* allocationCallbacks{nullptr};
+ bool useFileCache{false};
};
} // namespace Graphics
{
Dali::Shader ShaderNewWithUniformBlock(std::string_view vertexShader, std::string_view fragmentShader, Shader::Hint::Value hints, std::string_view shaderName, std::vector<Dali::UniformBlock> uniformBlocks)
{
- Internal::ShaderPtr shader = Dali::Internal::Shader::New(vertexShader, fragmentShader, hints, shaderName, std::move(uniformBlocks));
+ Internal::ShaderPtr shader = Dali::Internal::Shader::New(vertexShader, fragmentShader, hints, shaderName, std::move(uniformBlocks), !shaderName.empty());
return Shader(shader.Get());
}
* @param[in] hints Hints for rendering
* @param[in] renderPassTag RenderPassTag to match shader data and render task.
* @param[in] name Shader name for debug.
+ * @param[in] useFileCache Whether to use file cache or not.
*/
- ShaderData(std::string vertexSource, std::string fragmentSource, const Dali::Shader::Hint::Value hints, uint32_t renderPassTag, std::string_view name)
+ ShaderData(std::string vertexSource, std::string fragmentSource, const Dali::Shader::Hint::Value hints, uint32_t renderPassTag, std::string_view name, bool useFileCache)
: mShaderHash(-1),
mVertexShader(StringToVector(vertexSource)),
mFragmentShader(StringToVector(fragmentSource)),
mHints(hints),
mSourceMode(Graphics::ShaderSourceMode::TEXT),
mRenderPassTag(renderPassTag),
- mName(name)
+ mName(name),
+ mUseFileCache(useFileCache)
{
UpdateShaderVersion(mVertexShader, mVertexShaderVersion);
UpdateShaderVersion(mFragmentShader, mFragmentShaderVersion);
* @param[in] hints Hints for rendering
* @param[in] renderPassTag RenderPassTag to match shader data and render task.
* @param[in] name Shader name for debug.
+ * @param[in] useFileCache Whether to use file cache or not.
*/
- ShaderData(std::string_view vertexSource, std::string_view fragmentSource, const Dali::Shader::Hint::Value hints, uint32_t renderPassTag, std::string_view name)
+ ShaderData(std::string_view vertexSource, std::string_view fragmentSource, const Dali::Shader::Hint::Value hints, uint32_t renderPassTag, std::string_view name, bool useFileCache)
: mShaderHash(-1),
mVertexShader(StringToVector(vertexSource)),
mFragmentShader(StringToVector(fragmentSource)),
mHints(hints),
mSourceMode(Graphics::ShaderSourceMode::TEXT),
mRenderPassTag(renderPassTag),
- mName(name)
+ mName(name),
+ mUseFileCache(useFileCache)
{
UpdateShaderVersion(mVertexShader, mVertexShaderVersion);
UpdateShaderVersion(mFragmentShader, mFragmentShaderVersion);
* @param[in] fragmentSource Source code for fragment program
* @param[in] hints Hints for rendering
* @param[in] renderPassTag RenderPassTag to match shader data and render task.
- * @param[in] name Shader name for debug.
+ * @param[in] name Shader name for debug.
+ * @param[in] useFileCache Whether to use file cache or not.
*/
- ShaderData(std::vector<char>& vertexSource, std::vector<char>& fragmentSource, const Dali::Shader::Hint::Value hints, uint32_t renderPassTag, std::string_view name)
+ ShaderData(std::vector<char>& vertexSource, std::vector<char>& fragmentSource, const Dali::Shader::Hint::Value hints, uint32_t renderPassTag, std::string_view name, bool useFileCache)
: mShaderHash(-1),
mVertexShader(vertexSource),
mFragmentShader(fragmentSource),
mHints(hints),
mSourceMode(Graphics::ShaderSourceMode::BINARY),
mRenderPassTag(renderPassTag),
- mName(name)
+ mName(name),
+ mUseFileCache(useFileCache)
{
UpdateShaderVersion(mVertexShader, mVertexShaderVersion);
UpdateShaderVersion(mFragmentShader, mFragmentShaderVersion);
return mFragmentShaderVersion;
}
+ /**
+ * Check whether to use file cache or not
+ */
+ bool IsUseFileCache() const
+ {
+ return mUseFileCache;
+ }
+
private: // Not implemented
ShaderData(const ShaderData& other); ///< no copying of this object
ShaderData& operator=(const ShaderData& rhs); ///< no copying of this object
std::string mName{""}; ///< Name for this shader
uint32_t mVertexShaderVersion; ///< Vertex shader version
uint32_t mFragmentShaderVersion; ///< Fragment shader version
+ bool mUseFileCache; ///< Whether to use file cache or not
};
} // namespace Internal
}
}
-ShaderDataPtr ShaderFactory::Load(std::string_view vertexSource, std::string_view fragmentSource, const Dali::Shader::Hint::Value hints, uint32_t renderPassTag, std::string_view name, size_t& shaderHash)
+ShaderDataPtr ShaderFactory::Load(std::string_view vertexSource, std::string_view fragmentSource, const Dali::Shader::Hint::Value hints, uint32_t renderPassTag, std::string_view name, size_t& shaderHash, bool useFileCache)
{
// Work out the filename for the binary that the glsl source will be compiled and linked to:
shaderHash = CalculateHash(vertexSource, fragmentSource);
shaderBinaryFilename(shaderHash, binaryShaderFilename);
// Allocate the structure that returns the loaded shader:
- shaderData = new ShaderData(vertexSource, fragmentSource, hints, renderPassTag, name);
+ shaderData = new ShaderData(vertexSource, fragmentSource, hints, renderPassTag, name, useFileCache);
shaderData->SetHashValue(shaderHash);
shaderData->GetBuffer().Clear();
* If the cache hits or the load succeeds, the buffer member of the returned ShaderData will
* contain a precompiled shader binary program which can be uploaded directly to GLES.
*
- * @param [in] vertexSource The vertex shader source code
- * @param [in] fragmentSource The fragment shader source code
- * @param [in] renderPassTag RenderPass the shaders are executed
- * @param [in] name The name of shaders are executed
- * @param [out] shaderHash Hash key created from vertex and fragment shader code
- * @return ShaderData containing the source and hash value, and additionally,
- * a compiled shader program binary if one could be found, else an
- * empty binary buffer cleared to size zero.
+ * @param [in] vertexSource The vertex shader source code
+ * @param [in] fragmentSource The fragment shader source code
+ * @param [in] renderPassTag RenderPass the shaders are executed
+ * @param [in] name The name of shaders are executed
+ * @param [out] shaderHash Hash key created from vertex and fragment shader code
+ * @param [in] useFileCache If true, it tries to load shader binary from file cache.
+ * @return ShaderData containing the source and hash value, and additionally,
+ * a compiled shader program binary if one could be found, else an
+ * empty binary buffer cleared to size zero.
*/
- Internal::ShaderDataPtr Load(std::string_view vertexSource, std::string_view fragmentSource, const Dali::Shader::Hint::Value hints, uint32_t renderPassTag, std::string_view name, size_t& shaderHash);
+ Internal::ShaderDataPtr Load(std::string_view vertexSource, std::string_view fragmentSource, const Dali::Shader::Hint::Value hints, uint32_t renderPassTag, std::string_view name, size_t& shaderHash, bool useFileCache);
/**
* @brief Saves shader to memory cache and filesystem.
std::string_view fragmentShader,
Dali::Shader::Hint::Value hints,
std::string_view shaderName,
- std::vector<Dali::UniformBlock> uniformBlocks)
+ std::vector<Dali::UniformBlock> uniformBlocks,
+ bool isInternal)
{
// create scene object first so it's guaranteed to exist for the event side
auto sceneObject = new SceneGraph::Shader();
AddShaderMessage(updateManager, transferOwnership);
services.RegisterObject(shader.Get());
- shader->UpdateShaderData(vertexShader, fragmentShader, DEFAULT_RENDER_PASS_TAG, hints, shaderName);
+ shader->UpdateShaderData(vertexShader, fragmentShader, DEFAULT_RENDER_PASS_TAG, hints, shaderName, isInternal);
// Connect UniformBlock without clean up cache
for(auto&& uniformBlock : uniformBlocks)
std::string_view fragmentSource,
uint32_t renderPassTag,
Dali::Shader::Hint::Value hints,
- std::string_view name)
+ std::string_view name,
+ bool isInternal)
{
// Try to load a pre-compiled shader binary for the source pair:
ThreadLocalStorage& tls = ThreadLocalStorage::Get();
ShaderFactory& shaderFactory = tls.GetShaderFactory();
size_t shaderHash;
- Internal::ShaderDataPtr shaderData = shaderFactory.Load(vertexSource, fragmentSource, hints, renderPassTag, name, shaderHash);
+ Internal::ShaderDataPtr shaderData = shaderFactory.Load(vertexSource, fragmentSource, hints, renderPassTag, name, shaderHash, isInternal);
std::vector<Internal::ShaderDataPtr>::iterator shaderDataIterator = std::find_if(mShaderDataList.begin(), mShaderDataList.end(), [&shaderData](const Internal::ShaderDataPtr& shaderDataItem) { return shaderDataItem->GetRenderPassTag() == shaderData->GetRenderPassTag(); });
if(shaderDataIterator != mShaderDataList.end())
std::string name(DEFAULT_SHADER_NAME);
GetShaderData(*map, vertex, fragment, renderPassTag, hints, name);
- UpdateShaderData(vertex, fragment, renderPassTag, hints, name);
+ UpdateShaderData(vertex, fragment, renderPassTag, hints, name, false);
}
}
else if(shaderMap.GetType() == Property::ARRAY)
std::string name(DEFAULT_SHADER_NAME);
GetShaderData(*map, vertex, fragment, renderPassTag, hints, name);
- UpdateShaderData(vertex, fragment, renderPassTag, hints, name);
+ UpdateShaderData(vertex, fragment, renderPassTag, hints, name, false);
}
}
}
std::string_view fragmentShader,
Dali::Shader::Hint::Value hints,
std::string_view shaderName,
- std::vector<Dali::UniformBlock> uniformBlocks);
+ std::vector<Dali::UniformBlock> uniformBlocks,
+ bool isInternal = false);
/**
* @copydoc Dali::Shader::New()
* @param[in] renderPassTag render pass tag of this shader data
* @param[in] hints Hints to define the geometry of the rendered object
* @param[in] name The name of shader data.
+ * @param[in] isInternal Whether this shader is internal or not.
*/
- void UpdateShaderData(std::string_view vertexShader, std::string_view fragmentShader, uint32_t renderPassTag, Dali::Shader::Hint::Value hints, std::string_view name);
+ void UpdateShaderData(std::string_view vertexShader, std::string_view fragmentShader, uint32_t renderPassTag, Dali::Shader::Hint::Value hints, std::string_view name, bool isInternal);
/**
* @brief Sets shader data from shaderMap.
auto createInfo = Graphics::ProgramCreateInfo();
createInfo.SetShaderState(shaderStates);
createInfo.SetName(shaderData->GetName());
+ createInfo.SetFileCaching(shaderData->IsUseFileCache());
auto graphicsProgram = mGraphicsController->CreateProgram(createInfo, nullptr);
program->SetGraphicsProgram(std::move(graphicsProgram), *mUniformBufferManager, shader.GetConnectedUniformBlocks()); // generates reflection, defines memory reqs
Shader Shader::New(std::string_view vertexShader,
std::string_view fragmentShader,
Hint::Value hints,
- std::string_view shaderName)
+ std::string_view shaderName,
+ bool useFileCache)
{
- Internal::ShaderPtr shader = Internal::Shader::New(vertexShader, fragmentShader, hints, shaderName, {});
+ Internal::ShaderPtr shader = Internal::Shader::New(vertexShader, fragmentShader, hints, shaderName, {}, useFileCache);
return Shader(shader.Get());
}
* @param[in] fragmentShader Fragment Shader code for the effect.
* @param[in] hints Hints to define the geometry of the rendered object
* @param[in] shaderName The name of this shader. (optional)
+ * @param[in] useFileCache Whether to cache the shader or not. default is false
* @return A handle to a shader effect
*/
static Shader New(std::string_view vertexShader,
std::string_view fragmentShader,
Hint::Value hints = Hint::NONE,
- std::string_view shaderName = "");
+ std::string_view shaderName = "",
+ bool useFileCache = false);
/**
* @brief Creates Shader.