[dali_2.3.29] Merge branch 'devel/master'
[platform/core/uifw/dali-core.git] / dali / internal / common / shader-data.h
1 #ifndef DALI_INTERNAL_SHADER_DATA_H
2 #define DALI_INTERNAL_SHADER_DATA_H
3
4 /*
5  * Copyright (c) 2024 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // EXTERNAL INCLUDES
22 #include <string>
23 #include <string_view>
24
25 // INTERNAL INCLUDES
26 #include <dali/graphics-api/graphics-types.h>
27 #include <dali/public-api/common/dali-vector.h>
28 #include <dali/public-api/object/ref-object.h>
29 #include <dali/public-api/rendering/shader.h> // ShaderHints
30
31 namespace Dali
32 {
33 namespace Internal
34 {
35 class ShaderData;
36 using ShaderDataPtr = IntrusivePtr<ShaderData>;
37
38 namespace
39 {
40 template<typename StdStringType>
41 inline std::vector<char> StringToVector(const StdStringType& str)
42 {
43   auto retval = std::vector<char>{};
44   retval.insert(retval.begin(), str.begin(), str.end());
45   retval.push_back('\0');
46   return retval;
47 }
48
49 } // namespace
50
51 /**
52  * ShaderData class.
53  * A container for shader source code and compiled binary byte code.
54  */
55 class ShaderData : public Dali::RefObject
56 {
57 public:
58   /**
59    * Constructor
60    * @param[in] vertexSource   Source code for vertex program
61    * @param[in] fragmentSource Source code for fragment program
62    * @param[in] hints          Hints for rendering
63    * @param[in] renderPassTag  RenderPassTag to match shader data and render task.
64    * @param[in] name           Shader name for debug.
65    */
66   ShaderData(std::string vertexSource, std::string fragmentSource, const Dali::Shader::Hint::Value hints, uint32_t renderPassTag, std::string_view name)
67   : mShaderHash(-1),
68     mVertexShader(StringToVector(vertexSource)),
69     mFragmentShader(StringToVector(fragmentSource)),
70     mHints(hints),
71     mSourceMode(Graphics::ShaderSourceMode::TEXT),
72     mRenderPassTag(renderPassTag),
73     mName(name)
74   {
75     UpdateShaderVersion(mVertexShader, mVertexShaderVersion);
76     UpdateShaderVersion(mFragmentShader, mFragmentShaderVersion);
77   }
78
79   /**
80    * Constructor
81    * @param[in] vertexSource   Source code for vertex program
82    * @param[in] fragmentSource Source code for fragment program
83    * @param[in] hints          Hints for rendering
84    * @param[in] renderPassTag  RenderPassTag to match shader data and render task.
85    * @param[in] name           Shader name for debug.
86    */
87   ShaderData(std::string_view vertexSource, std::string_view fragmentSource, const Dali::Shader::Hint::Value hints, uint32_t renderPassTag, std::string_view name)
88   : mShaderHash(-1),
89     mVertexShader(StringToVector(vertexSource)),
90     mFragmentShader(StringToVector(fragmentSource)),
91     mHints(hints),
92     mSourceMode(Graphics::ShaderSourceMode::TEXT),
93     mRenderPassTag(renderPassTag),
94     mName(name)
95   {
96     UpdateShaderVersion(mVertexShader, mVertexShaderVersion);
97     UpdateShaderVersion(mFragmentShader, mFragmentShaderVersion);
98   }
99
100   /**
101    * Creates a shader data containing binary content
102    * @param[in] vertexSource   Source code for vertex program
103    * @param[in] fragmentSource Source code for fragment program
104    * @param[in] hints          Hints for rendering
105    * @param[in] renderPassTag  RenderPassTag to match shader data and render task.
106    * @param[in] name Shader name for debug.
107    */
108   ShaderData(std::vector<char>& vertexSource, std::vector<char>& fragmentSource, const Dali::Shader::Hint::Value hints, uint32_t renderPassTag, std::string_view name)
109   : mShaderHash(-1),
110     mVertexShader(vertexSource),
111     mFragmentShader(fragmentSource),
112     mHints(hints),
113     mSourceMode(Graphics::ShaderSourceMode::BINARY),
114     mRenderPassTag(renderPassTag),
115     mName(name)
116   {
117     UpdateShaderVersion(mVertexShader, mVertexShaderVersion);
118     UpdateShaderVersion(mFragmentShader, mFragmentShaderVersion);
119   }
120
121   /**
122    * Query whether a shader hint is set.
123    *
124    * @warning This method is called from Update Algorithms.
125    *
126    * @pre The shader has been initialized.
127    * @param[in] hint The hint to check.
128    * @return True if the given hint is set.
129    */
130   [[nodiscard]] bool HintEnabled(Dali::Shader::Hint::Value hint) const
131   {
132     return mHints & hint;
133   }
134
135 protected:
136   /**
137    * Protected Destructor
138    * A reference counted object may only be deleted by calling Unreference()
139    */
140   ~ShaderData() override
141   {
142     // vector releases its data
143   }
144
145 public: // API
146   /**
147    * Set hash value which is created with vertex and fragment shader code
148    * @param [in] shaderHash  hash key created with vertex and fragment shader code
149    */
150   void SetHashValue(size_t shaderHash)
151   {
152     DALI_ASSERT_DEBUG(shaderHash != size_t(-1));
153     mShaderHash = shaderHash;
154   }
155
156   /**
157    * Get hash value which is created with vertex and fragment shader code
158    * @return shaderHash  hash key created with vertex and fragment shader code
159    */
160   size_t GetHashValue() const
161   {
162     DALI_ASSERT_DEBUG(mShaderHash != size_t(-1));
163     return mShaderHash;
164   }
165
166   /**
167    * @return the vertex shader
168    */
169   const char* GetVertexShader() const
170   {
171     return &mVertexShader[0];
172   }
173
174   /**
175    * @return the vertex shader
176    */
177   const char* GetFragmentShader() const
178   {
179     return &mFragmentShader[0];
180   }
181
182   /**
183    * Returns a std::vector containing the shader code associated with particular pipeline stage
184    * @param[in] the graphics pipeline stage
185    * @return the shader code
186    */
187   const std::vector<char>& GetShaderForPipelineStage(Graphics::PipelineStage stage) const
188   {
189     if(stage == Graphics::PipelineStage::VERTEX_SHADER)
190     {
191       return mVertexShader;
192     }
193     else if(stage == Graphics::PipelineStage::FRAGMENT_SHADER)
194     {
195       return mFragmentShader;
196     }
197     else
198     {
199       //      DALI_LOG_ERROR("Unsupported shader stage\n");
200       static const std::vector<char> emptyShader;
201       return emptyShader;
202     }
203   }
204
205   /**
206    * @return the hints
207    */
208   Dali::Shader::Hint::Value GetHints() const
209   {
210     return mHints;
211   }
212   /**
213    * Check whether there is a compiled binary available
214    * @return true if this objects contains a compiled binary
215    */
216   bool HasBinary() const
217   {
218     return 0 != mBuffer.Size();
219   }
220
221   /**
222    * Allocate a buffer for the compiled binary bytecode
223    * @param[in] size  The size of the buffer in bytes
224    */
225   void AllocateBuffer(std::size_t size)
226   {
227     mBuffer.Resize(size);
228   }
229
230   /**
231    * Get the program buffer
232    * @return reference to the buffer
233    */
234   std::size_t GetBufferSize() const
235   {
236     return mBuffer.Size();
237   }
238
239   /**
240    * Get the data that the buffer points to
241    * @return raw pointer to the buffer data
242    */
243   uint8_t* GetBufferData()
244   {
245     DALI_ASSERT_DEBUG(mBuffer.Size() > 0);
246     return &mBuffer[0];
247   }
248
249   /**
250    * Get the data that the buffer points to
251    * @return raw pointer to the buffer data
252    */
253   Dali::Vector<uint8_t>& GetBuffer()
254   {
255     return mBuffer;
256   }
257
258   /**
259    * Get the source mode of shader data
260    * @return the source mode of shader data ( text or binary )
261    */
262   Graphics::ShaderSourceMode GetSourceMode() const
263   {
264     return mSourceMode;
265   }
266
267   /**
268    * Get Render Pass of shader data
269    * @return RenderPassTag for Render Pass of this shader data, Default value is 0.
270    */
271   uint32_t GetRenderPassTag() const
272   {
273     return mRenderPassTag;
274   }
275
276   /**
277    * Get Name of shader data
278    * @return Name for this shader data, Default value is empty string.
279    */
280   const std::string& GetName() const
281   {
282     return mName;
283   }
284
285   /**
286    * Returns DALi specific vertex shader version
287    * @return valid version number
288    */
289   uint32_t GetVertexShaderVersion() const
290   {
291     return mVertexShaderVersion;
292   }
293
294   /**
295    * Returns DALi specific fragment shader version
296    * @return valid version number
297    */
298   uint32_t GetFragmentShaderVersion() const
299   {
300     return mFragmentShaderVersion;
301   }
302
303 private:                                        // Not implemented
304   ShaderData(const ShaderData& other);          ///< no copying of this object
305   ShaderData& operator=(const ShaderData& rhs); ///< no copying of this object
306
307 private:
308   /**
309    * Updates shader version.
310    */
311   void UpdateShaderVersion(std::vector<char>& code, uint32_t& outVersion)
312   {
313     // The version may be updated only for GLSL language.
314     // If we support direct SPIRV this will be skipped
315     std::string_view strView = code.data();
316
317     // find first occurence of 'version' tag
318     // the tag is expected at the start of line
319     static const std::string VERSION_TAG = "//@version";
320
321     auto pos = strView.find(VERSION_TAG);
322     if(pos != std::string_view::npos && (pos == 0 || strView[pos - 1] == '\n'))
323     {
324       char* end;
325       // Update version
326       outVersion = std::strtoul(strView.data() + pos + VERSION_TAG.length(), &end, 10);
327     }
328     else
329     {
330       outVersion = 0;
331     }
332   }
333
334 private:                                             // Data
335   std::size_t                mShaderHash;            ///< hash key created with vertex and fragment shader code
336   std::vector<char>          mVertexShader;          ///< source code for vertex program
337   std::vector<char>          mFragmentShader;        ///< source code for fragment program
338   Dali::Shader::Hint::Value  mHints;                 ///< take a hint
339   Dali::Vector<uint8_t>      mBuffer;                ///< buffer containing compiled binary bytecode
340   Graphics::ShaderSourceMode mSourceMode;            ///< Source mode of shader data ( text or binary )
341   uint32_t                   mRenderPassTag{0u};     ///< Render Pass Tag for this shader
342   std::string                mName{""};              ///< Name for this shader
343   uint32_t                   mVertexShaderVersion;   ///< Vertex shader version
344   uint32_t                   mFragmentShaderVersion; ///< Fragment shader version
345 };
346
347 } // namespace Internal
348
349 } // namespace Dali
350
351 #endif // DALI_INTERNAL_SHADER_DATA_H