[Tizen] Apply precompile shader
authorJaehyun Cho <jae_hyun.cho@samsung.com>
Wed, 15 Nov 2023 06:02:13 +0000 (15:02 +0900)
committerJaehyun Cho <jae_hyun.cho@samsung.com>
Wed, 15 Nov 2023 06:02:13 +0000 (15:02 +0900)
This reverts commit c0e59f29352fd70e98f858ad3fd65cd21b2f8869.

dali/integration-api/core.cpp
dali/integration-api/core.h
dali/integration-api/file.list
dali/integration-api/shader-precompiler.cpp [new file with mode: 0644]
dali/integration-api/shader-precompiler.h [new file with mode: 0644]
dali/internal/common/core-impl.cpp
dali/internal/common/core-impl.h
dali/internal/render/common/render-manager.cpp
dali/internal/render/common/render-manager.h

index 9caab22..112b64a 100644 (file)
@@ -130,6 +130,11 @@ void Core::RenderScene(RenderStatus& status, Integration::Scene& scene, bool ren
   mImpl->RenderScene(status, scene, renderToFbo, clippingRect);
 }
 
+void Core::PreCompileShader(const std::string& vertexShader, const std::string& fragmentShader)
+{
+  mImpl->PreCompileShader(vertexShader, fragmentShader);
+}
+
 void Core::PostRender()
 {
   mImpl->PostRender();
index c8d2a61..6a0748d 100644 (file)
@@ -387,6 +387,14 @@ public:
   void RenderScene(RenderStatus& status, Integration::Scene& scene, bool renderToFbo, Rect<int>& clippingRect);
 
   /**
+   * Precompile shaders for launching time
+   *
+   * @param[in] vertexShader vertexShader need to precompile
+   * @param[in] fragmentShader fragmentShader need to precompile
+  */
+  void PreCompileShader(const std::string& vertexShader, const std::string& fragmentShader);
+
+  /**
    * This is called after rendering all the scenes in the next frame. This method should be
    * followed by a call up RenderScene.
    * Multi-threading note: this method should be called from a dedicated rendering thread.
index 1059719..866aa27 100644 (file)
@@ -13,8 +13,9 @@ SET( platform_abstraction_src_files
    ${platform_abstraction_src_dir}/profiling.cpp
    ${platform_abstraction_src_dir}/render-task-list-integ.cpp
    ${platform_abstraction_src_dir}/scene.cpp
+   ${platform_abstraction_src_dir}/shader-precompiler.cpp
    ${platform_abstraction_src_dir}/texture-integ.cpp
-   ${platform_abstraction_src_dir}/trace.cpp
+   ${platform_abstraction_src_dir}/trace.cpp  
 )
 
 SET( platform_abstraction_events_src_files
@@ -51,6 +52,7 @@ SET( platform_abstraction_header_files
    ${platform_abstraction_src_dir}/resource-policies.h
    ${platform_abstraction_src_dir}/resource-types.h
    ${platform_abstraction_src_dir}/scene.h
+   ${platform_abstraction_src_dir}/shader-precompiler.h
    ${platform_abstraction_src_dir}/texture-integ.h
    ${platform_abstraction_src_dir}/trace.h
 )
diff --git a/dali/integration-api/shader-precompiler.cpp b/dali/integration-api/shader-precompiler.cpp
new file mode 100644 (file)
index 0000000..ad8efcf
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// CLASS HEADER
+#include <dali/integration-api/shader-precompiler.h>
+
+// INTERNAL HEADER
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+std::unique_ptr<ShaderPrecompiler> ShaderPrecompiler::mInstance = nullptr;
+std::once_flag ShaderPrecompiler::mOnceFlag;
+
+ShaderPrecompiler::ShaderPrecompiler()
+: mRawShaderData(),
+  mPrecompiled(false),
+  mEnabled(false)
+{
+}
+
+ShaderPrecompiler& ShaderPrecompiler::Get()
+{
+  std::call_once(mOnceFlag, []()
+                 { mInstance.reset(new ShaderPrecompiler); });
+
+  return *(mInstance.get());
+}
+
+void ShaderPrecompiler::GetPrecompileShaderList(RawShaderData& shaders)
+{
+  ConditionalWait::ScopedLock lock(mConditionalWait);
+  if(!IsReady())
+  {
+    DALI_LOG_RELEASE_INFO("Precompiled shader list is not ready yet, need to wait \n");
+    mConditionalWait.Wait(lock);
+  }
+
+  // move shader list
+  shaders = mRawShaderData;
+}
+
+void ShaderPrecompiler::SavePrecomipleShaderList(RawShaderData& shaders)
+{
+  ConditionalWait::ScopedLock lock(mConditionalWait);
+  mRawShaderData.vertexPrefix = shaders.vertexPrefix;
+  mRawShaderData.fragmentPrefix = shaders.fragmentPrefix;
+  mRawShaderData.vertexShader = shaders.vertexShader;
+  mRawShaderData.fragmentShader = shaders.fragmentShader;
+  mRawShaderData.shaderCount = shaders.shaderCount;
+
+  mPrecompiled = true;
+  mConditionalWait.Notify(lock);
+}
+
+bool ShaderPrecompiler::IsReady() const
+{
+  return mPrecompiled;
+}
+
+void ShaderPrecompiler::Enable()
+{
+  mEnabled = true;
+}
+
+bool ShaderPrecompiler::IsEnable()
+{
+  return mEnabled;
+}
+
+
+} // namespace Integration
+} // namespace Dali
diff --git a/dali/integration-api/shader-precompiler.h b/dali/integration-api/shader-precompiler.h
new file mode 100644 (file)
index 0000000..1c2094b
--- /dev/null
@@ -0,0 +1,129 @@
+#ifndef DALI_INTEGRATION_SHADER_PRECOMPILER_H
+#define DALI_INTEGRATION_SHADER_PRECOMPILER_H
+
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL HEADER
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/object/base-handle.h>
+#include <dali/devel-api/threading/conditional-wait.h>
+#include <dali/devel-api/threading/mutex.h>
+
+// EXTERNAL HEDAER
+#include <string_view>
+#include <memory>
+#include <mutex>
+
+namespace Dali
+{
+namespace Internal DALI_INTERNAL
+{
+class ShaderPrecompiler;
+}
+
+struct RawShaderData
+{
+  int shaderCount;
+  std::vector<std::string_view> vertexPrefix;
+  std::vector<std::string_view> fragmentPrefix;
+  std::string_view vertexShader;
+  std::string_view fragmentShader;
+};
+
+namespace Integration
+{
+/**
+ * ShaderPrecompiler  is used to precompile shaders.
+ * The precompiled shaders are stored in a file.
+ * @SINCE_2_2.45
+ */
+class DALI_CORE_API ShaderPrecompiler : public BaseHandle
+{
+public:
+  /**
+   * @brief Gets the singleton of ShaderPrecompiler object.
+   *
+   * @SINCE_2_2.45
+   * @return A handle to the ShaderPrecompiler
+   */
+  static ShaderPrecompiler& Get();
+
+  /**
+   * @brief Get the precompile shader list.
+   *
+   *  @SINCE_2_2.45
+   *  @param[in] shaders shader data for precompile
+  */
+  void GetPrecompileShaderList(RawShaderData& shaders);
+
+  /**
+   * @brief Save the precompile shader list.
+   *
+   * @SINCE_2_2.45
+   * @param[in] shaders shader data for precompile
+  */
+  void SavePrecomipleShaderList(RawShaderData& shaders);
+
+  /**
+   * @brief Check precompile list is ready or not
+   *
+   * @SINCE_2_2.45
+   * @return true if precompile list is ready
+  */
+  bool IsReady() const;
+
+  /**
+   * @brief Enable the feature of precompile
+   *
+   * @SINCE_2_2.45
+  */
+  void Enable();
+
+  /**
+   * @brief Check the feature of precompile is enabled or not
+   *
+   * @SINCE_2_2.45
+   * @return true if the feature of precompile is enabled
+  */
+  bool IsEnable();
+
+  /**
+   * Construct a new ShaderPrecompiler.
+   */
+  ShaderPrecompiler();
+
+  // Undefined
+  ShaderPrecompiler(const ShaderPrecompiler&) = delete;
+
+  // Undefined
+  ShaderPrecompiler& operator=(const ShaderPrecompiler& rhs) = delete;
+
+private:
+  static std::unique_ptr<ShaderPrecompiler> mInstance;
+  static std::once_flag mOnceFlag;
+  RawShaderData mRawShaderData;
+  ConditionalWait mConditionalWait;
+  bool mPrecompiled;
+  bool mEnabled;
+};
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // DALI_INTEGRATION_SHADER_PRECOMPILER_H
index 3714d35..800a04d 100644 (file)
@@ -232,6 +232,11 @@ void Core::RenderScene(RenderStatus& status, Integration::Scene& scene, bool ren
   mRenderManager->RenderScene(status, scene, renderToFbo, clippingRect);
 }
 
+void Core::PreCompileShader(const std::string& vertexShader, const std::string& fragmentShader)
+{
+  mRenderManager->PreCompileShader(vertexShader, fragmentShader);
+}
+
 void Core::PostRender()
 {
   mUpdateManager->PostRender();
index 754869c..6e9d72c 100644 (file)
@@ -146,6 +146,11 @@ public:
   void RenderScene(Integration::RenderStatus& status, Integration::Scene& scene, bool renderToFbo, Rect<int>& clippingRect);
 
   /**
+   * @copydoc Dali::Integration::Core::PreCompileShader()
+   */
+  void PreCompileShader(const std::string& vertexShader, const std::string& fragmentShader);
+
+  /**
    * @copydoc Dali::Integration::Core::Render()
    */
   void PostRender();
index 6d42e84..a83dde6 100644 (file)
@@ -1116,6 +1116,51 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration::
   }
 }
 
+void RenderManager::PreCompileShader(const std::string& vertexShader, const std::string& fragmentShader)
+{
+  uint32_t renderPassTag{0u};
+  Dali::Shader::Hint::Value hints = Dali::Shader::Hint::NONE;
+  auto shaderHash = CalculateHash(vertexShader.data(), fragmentShader.data());
+  auto shaderData = new ShaderData(std::string(vertexShader.data()), std::string(fragmentShader.data()), hints, renderPassTag);
+  shaderData->SetHashValue(shaderHash);
+  auto program = Program::New(mImpl->programController, shaderData, mImpl->graphicsController);
+  if(!program)
+  {
+    DALI_LOG_RELEASE_INFO("Fail to create program \n");
+  }
+  else
+  {
+    // If program doesn't have Gfx program object assigned yet, prepare it.
+    if(!program->GetGraphicsProgramPtr())
+    {
+      const std::vector<char>& vertShader   = shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::VERTEX_SHADER);
+      const std::vector<char>& fragShader   = shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER);
+      Dali::Graphics::Shader&  vertexShader = mImpl->shaderCache.GetShader(
+        vertShader,
+        Graphics::PipelineStage::VERTEX_SHADER,
+        shaderData->GetSourceMode());
+
+      Dali::Graphics::Shader& fragmentShader = mImpl->shaderCache.GetShader(
+        fragShader,
+        Graphics::PipelineStage::FRAGMENT_SHADER,
+        shaderData->GetSourceMode());
+
+      std::vector<Graphics::ShaderState> shaderStates{
+        Graphics::ShaderState()
+          .SetShader(vertexShader)
+          .SetPipelineStage(Graphics::PipelineStage::VERTEX_SHADER),
+        Graphics::ShaderState()
+          .SetShader(fragmentShader)
+          .SetPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER)};
+
+      auto createInfo = Graphics::ProgramCreateInfo();
+      createInfo.SetShaderState(shaderStates);
+      auto graphicsProgram = mImpl->graphicsController.CreateProgram(createInfo, nullptr);
+      program->SetGraphicsProgram(std::move(graphicsProgram), *(mImpl->uniformBufferManager.get())); // generates reflection
+    }
+  }
+}
+
 void RenderManager::PostRender()
 {
   if(!mImpl->commandBufferSubmitted)
index 4d355cb..fc955ea 100644 (file)
@@ -408,6 +408,14 @@ public:
    */
   void RenderScene(Integration::RenderStatus& status, Integration::Scene& scene, bool renderToFbo, Rect<int>& clippingRect);
 
+  /**
+   * Precompile shaders for launching time
+   *
+   * @param[in] vertexShader vertexShader need to precompile
+   * @param[in] fragmentShader fragmentShader need to precompile
+  */
+  void PreCompileShader(const std::string& vertexShader, const std::string& fragmentShader);
+
   // This method should be called from Core::PostRender()
 
   /**