Merge "Added shader support to pipeline cache" into devel/master
[platform/core/uifw/dali-adaptor.git] / dali / internal / graphics / gles-impl / gles-graphics-shader.cpp
1 /*
2  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include "gles-graphics-shader.h"
20
21 // INTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23 #include "egl-graphics-controller.h"
24
25 namespace Dali::Graphics::GLES
26 {
27 struct ShaderImpl::Impl
28 {
29   explicit Impl(Graphics::EglGraphicsController& _controller, const Graphics::ShaderCreateInfo& _createInfo)
30   : controller(_controller)
31   {
32     createInfo.pipelineStage  = _createInfo.pipelineStage;
33     createInfo.shaderlanguage = _createInfo.shaderlanguage;
34     createInfo.sourceMode     = _createInfo.sourceMode;
35     createInfo.sourceSize     = _createInfo.sourceSize;
36
37     // Make a copy of source code
38     source.resize(_createInfo.sourceSize);
39     std::copy(reinterpret_cast<const char*>(_createInfo.sourceData),
40               reinterpret_cast<const char*>(_createInfo.sourceData) + _createInfo.sourceSize,
41               source.data());
42
43     // Substitute pointer
44     createInfo.sourceData = source.data();
45   }
46
47   ~Impl(){};
48
49   bool Compile()
50   {
51     auto gl = controller.GetGL();
52
53     if(!gl)
54     {
55       return false;
56     }
57
58     if(!glShader)
59     {
60       GLenum pipelineStage{0u};
61       switch(createInfo.pipelineStage)
62       {
63         case Graphics::PipelineStage::TOP_OF_PIPELINE:
64         {
65           break;
66         }
67         case Graphics::PipelineStage::VERTEX_SHADER:
68         {
69           pipelineStage = GL_VERTEX_SHADER;
70           break;
71         }
72         case Graphics::PipelineStage::GEOMETRY_SHADER:
73         {
74           break;
75         }
76         case Graphics::PipelineStage::FRAGMENT_SHADER:
77         {
78           pipelineStage = GL_FRAGMENT_SHADER;
79           break;
80         }
81         case Graphics::PipelineStage::COMPUTE_SHADER:
82         {
83           break;
84         }
85         case Graphics::PipelineStage::TESSELATION_CONTROL:
86         {
87           break;
88         }
89         case Graphics::PipelineStage::TESSELATION_EVALUATION:
90         {
91           break;
92         }
93         case Graphics::PipelineStage::BOTTOM_OF_PIPELINE:
94         {
95           break;
96         }
97       }
98
99       if(pipelineStage)
100       {
101         auto       shader = gl->CreateShader(pipelineStage);
102         const auto src    = reinterpret_cast<const char*>(createInfo.sourceData);
103         GLint      size   = createInfo.sourceSize;
104         gl->ShaderSource(shader, 1, const_cast<const char**>(&src), &size);
105         gl->CompileShader(shader);
106
107         GLint status{0};
108         gl->GetShaderiv(shader, GL_COMPILE_STATUS, &status);
109         if(status != GL_TRUE)
110         {
111           char    output[4096];
112           GLsizei size{0u};
113           gl->GetShaderInfoLog(shader, 4096, &size, output);
114           DALI_LOG_ERROR("Code: %s\n", reinterpret_cast<const char*>(createInfo.sourceData));
115           DALI_LOG_ERROR("glCompileShader() failed: \n%s\n", output);
116           gl->DeleteShader(shader);
117           return false;
118         }
119         glShader = shader;
120       }
121       return true;
122     }
123     return true;
124   }
125
126   void Destroy()
127   {
128     auto gl = controller.GetGL();
129
130     if(gl && glShader)
131     {
132       gl->DeleteShader(glShader);
133       glShader = 0;
134     }
135   }
136
137   EglGraphicsController& controller;
138   ShaderCreateInfo       createInfo;
139   std::vector<char>      source{};
140
141   uint32_t glShader{};
142   uint32_t refCount{0u};
143   uint32_t flushCount{0u}; ///< Number of frames at refCount=0
144 };
145
146 ShaderImpl::ShaderImpl(const Graphics::ShaderCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
147 {
148   mImpl = std::make_unique<Impl>(controller, createInfo);
149 }
150
151 ShaderImpl::~ShaderImpl()
152 {
153   if(!mImpl->controller.IsShuttingDown())
154   {
155     mImpl->Destroy();
156   }
157 }
158
159 uint32_t ShaderImpl::Retain()
160 {
161   mImpl->flushCount = 0;
162   return ++mImpl->refCount;
163 }
164
165 uint32_t ShaderImpl::Release()
166 {
167   uint32_t remainingCount = --mImpl->refCount;
168   mImpl->flushCount       = 0;
169   return remainingCount;
170 }
171
172 [[nodiscard]] uint32_t ShaderImpl::GetRefCount() const
173 {
174   return mImpl->refCount;
175 }
176
177 [[nodiscard]] uint32_t ShaderImpl::IncreaseFlushCount()
178 {
179   return ++mImpl->flushCount;
180 }
181
182 [[nodiscard]] uint32_t ShaderImpl::GetFlushCount() const
183 {
184   return mImpl->flushCount;
185 }
186
187 /**
188  * @brief Compiles shader
189  *
190  * @return True on success
191  */
192 [[nodiscard]] bool ShaderImpl::Compile() const
193 {
194   return mImpl->Compile();
195 }
196
197 [[nodiscard]] uint32_t ShaderImpl::GetGLShader() const
198 {
199   return mImpl->glShader;
200 }
201
202 const ShaderCreateInfo& ShaderImpl::GetCreateInfo() const
203 {
204   return mImpl->createInfo;
205 }
206
207 [[nodiscard]] EglGraphicsController& ShaderImpl::GetController() const
208 {
209   return mImpl->controller;
210 }
211
212 Shader::~Shader()
213 {
214   if(!mShader->Release())
215   {
216     GetImplementation()->GetController().GetPipelineCache().MarkShaderCacheFlushRequired();
217   }
218 }
219
220 [[nodiscard]] const ShaderCreateInfo& Shader::GetCreateInfo() const
221 {
222   return GetImplementation()->GetCreateInfo();
223 }
224
225 void Shader::DiscardResource()
226 {
227   auto& controller = GetImplementation()->GetController();
228   if(!controller.IsShuttingDown())
229   {
230     controller.DiscardResource(this);
231   }
232 }
233
234 } // namespace Dali::Graphics::GLES