• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "shader.h"
17 
18 #include <algorithm>
19 #include <3d/render/default_material_constants.h>
20 #include <render/device/intf_gpu_resource_manager.h>
21 
22 #include <meta/api/make_callback.h>
23 
24 #include "../util.h"
25 
SCENE_BEGIN_NAMESPACE()26 SCENE_BEGIN_NAMESPACE()
27 
28 BASE_NS::string Shader::GetName() const
29 {
30     return Name()->GetValue();
31 }
32 
SetRenderHandleImpl(const IInternalScene::Ptr & scene,RENDER_NS::RenderHandleReference handle)33 bool Shader::SetRenderHandleImpl(const IInternalScene::Ptr& scene, RENDER_NS::RenderHandleReference handle)
34 {
35     handle_ = handle;
36     return true;
37 }
38 
SetRenderHandle(const IInternalScene::Ptr & scene,RENDER_NS::RenderHandleReference handle,CORE_NS::EntityReference ent)39 bool Shader::SetRenderHandle(
40     const IInternalScene::Ptr& scene, RENDER_NS::RenderHandleReference handle, CORE_NS::EntityReference ent)
41 {
42     return SetShaderState(scene, handle, ent, {}, {});
43 }
44 
SetShaderState(const IInternalScene::Ptr & scene,RENDER_NS::RenderHandleReference handle,CORE_NS::EntityReference ent,RENDER_NS::RenderHandleReference ghandle,CORE_NS::EntityReference gstate)45 bool Shader::SetShaderState(const IInternalScene::Ptr& scene, RENDER_NS::RenderHandleReference handle,
46     CORE_NS::EntityReference ent, RENDER_NS::RenderHandleReference ghandle, CORE_NS::EntityReference gstate)
47 {
48     {
49         std::shared_lock lock { mutex_ };
50         if (handle_.GetHandle() == handle.GetHandle() && entity_ == ent && graphicsState_ == gstate &&
51             graphicsStateHandle_.GetHandle() == ghandle.GetHandle()) {
52             return true;
53         }
54     }
55 
56     RENDER_NS::IShaderManager::IdDesc desc;
57     scene
58         ->AddTask([&] {
59             auto& shaderMgr = scene->GetRenderContext().GetDevice().GetShaderManager();
60 
61             if (auto rhman = static_cast<CORE3D_NS::IRenderHandleComponentManager*>(
62                     scene->GetEcsContext().FindComponent<CORE3D_NS::RenderHandleComponent>())) {
63                 auto renderSlotId =
64                     shaderMgr.GetRenderSlotId(CORE3D_NS::DefaultMaterialShaderConstants::RENDER_SLOT_FORWARD_OPAQUE);
65                 auto rsd = shaderMgr.GetRenderSlotData(renderSlotId);
66 
67                 if (handle) {
68                     if (!ent) {
69                         ent = HandleFromRenderResource(scene, handle);
70                     }
71                     desc = shaderMgr.GetIdDesc(handle);
72                 } else {
73                     desc = shaderMgr.GetIdDesc(rsd.shader);
74                 }
75                 if (!ghandle) {
76                     ghandle = UpdateGraphicsState(scene, shaderMgr.GetGraphicsState(rsd.graphicsState));
77                 }
78                 if (!gstate) {
79                     gstate = HandleFromRenderResource(scene, ghandle);
80                 }
81                 if (auto m = rhman->Write(gstate)) {
82                     m->reference = ghandle;
83                 }
84             }
85         })
86         .Wait();
87 
88     {
89         std::unique_lock lock { mutex_ };
90         handle_ = handle;
91         entity_ = ent;
92         graphicsState_ = gstate;
93         graphicsStateHandle_ = ghandle;
94         scene_ = scene;
95     }
96     META_ACCESS_PROPERTY(Uri)->SetValue(desc.path);
97     META_ACCESS_PROPERTY(Name)->SetValue(desc.displayName);
98     META_NS::Invoke<META_NS::IOnChanged>(EventOnResourceChanged(META_NS::MetadataQuery::EXISTING));
99     return true;
100 }
GetRenderHandle() const101 RENDER_NS::RenderHandleReference Shader::GetRenderHandle() const
102 {
103     std::shared_lock lock { mutex_ };
104     return handle_;
105 }
GetEntity() const106 CORE_NS::Entity Shader::GetEntity() const
107 {
108     std::shared_lock lock { mutex_ };
109     return entity_;
110 }
111 
SetGraphicsState(CORE_NS::EntityReference gstate)112 bool Shader::SetGraphicsState(CORE_NS::EntityReference gstate)
113 {
114     std::unique_lock lock { mutex_ };
115     graphicsState_ = gstate;
116     return true;
117 }
GetGraphicsState() const118 CORE_NS::EntityReference Shader::GetGraphicsState() const
119 {
120     std::shared_lock lock { mutex_ };
121     return graphicsState_;
122 }
123 
LoadShader(const IScene::Ptr & s,BASE_NS::string_view uri)124 Future<bool> Shader::LoadShader(const IScene::Ptr& s, BASE_NS::string_view uri)
125 {
126     if (auto inter = s->GetInternalScene()) {
127         return inter->AddTask([=, path = BASE_NS::string(uri)] {
128             auto& man = inter->GetRenderContext().GetDevice().GetShaderManager();
129             man.LoadShaderFile(path);
130             auto handle = man.GetShaderHandle(path);
131             if (handle) {
132                 // t: notify in correct thread
133                 SetShaderState(inter, handle, {}, man.GetGraphicsStateHandleByShaderHandle(handle), {});
134             }
135             return static_cast<bool>(handle);
136         });
137     }
138     return {};
139 }
140 
GetScene() const141 IInternalScene::Ptr Shader::GetScene() const
142 {
143     std::shared_lock lock { mutex_ };
144     return scene_.lock();
145 }
146 
GetGraphicsStateHandle() const147 RENDER_NS::RenderHandleReference Shader::GetGraphicsStateHandle() const
148 {
149     std::shared_lock lock { mutex_ };
150     return graphicsStateHandle_;
151 }
152 
GetRenderSlot(const RENDER_NS::GraphicsState & gs)153 static BASE_NS::string_view GetRenderSlot(const RENDER_NS::GraphicsState& gs)
154 {
155     return std::any_of(gs.colorBlendState.colorAttachments,
156         gs.colorBlendState.colorAttachments + gs.colorBlendState.colorAttachmentCount,
157         [](const RENDER_NS::GraphicsState::ColorBlendState::Attachment& attachment) {
158             return attachment.enableBlend;
159         })
160         ? CORE3D_NS::DefaultMaterialShaderConstants::RENDER_SLOT_FORWARD_TRANSLUCENT
161         : CORE3D_NS::DefaultMaterialShaderConstants::RENDER_SLOT_FORWARD_OPAQUE;
162 }
163 
UpdateGraphicsState(const IInternalScene::Ptr & scene,const RENDER_NS::GraphicsState & gs)164 RENDER_NS::RenderHandleReference Shader::UpdateGraphicsState(
165     const IInternalScene::Ptr& scene, const RENDER_NS::GraphicsState& gs)
166 {
167     auto& man = scene->GetRenderContext().GetDevice().GetShaderManager();
168     RENDER_NS::IShaderManager::GraphicsStateVariantCreateInfo vinfo { GetRenderSlot(gs) };
169     auto handle = man.CreateGraphicsState({ BASE_NS::string(BASE_NS::to_string(intptr_t(this))), gs }, vinfo);
170     std::unique_lock lock { mutex_ };
171     if (graphicsStateHandle_.GetHandle() != handle.GetHandle()) {
172         if (auto rhman = static_cast<CORE3D_NS::IRenderHandleComponentManager*>(
173                 scene->GetEcsContext().FindComponent<CORE3D_NS::RenderHandleComponent>())) {
174             graphicsStateHandle_ = handle;
175             if (auto m = rhman->Write(graphicsState_)) {
176                 m->reference = graphicsStateHandle_;
177             }
178         }
179     }
180     return graphicsStateHandle_;
181 }
182 
GetCullMode() const183 Future<CullModeFlags> Shader::GetCullMode() const
184 {
185     if (auto inter = GetScene()) {
186         return inter->AddTask([=] {
187             if (auto h = GetGraphicsStateHandle()) {
188                 auto& man = inter->GetRenderContext().GetDevice().GetShaderManager();
189                 auto gs = man.GetGraphicsState(h);
190                 return static_cast<CullModeFlags>(gs.rasterizationState.cullModeFlags);
191             }
192             return CullModeFlags {};
193         });
194     }
195     return {};
196 }
197 
SetCullMode(CullModeFlags cullMode)198 Future<bool> Shader::SetCullMode(CullModeFlags cullMode)
199 {
200     if (auto inter = GetScene()) {
201         return inter->AddTask([=] {
202             auto h = GetGraphicsStateHandle();
203             if (h) {
204                 auto& man = inter->GetRenderContext().GetDevice().GetShaderManager();
205                 auto gs = man.GetGraphicsState(h);
206                 gs.rasterizationState.cullModeFlags = static_cast<RENDER_NS::CullModeFlags>(cullMode);
207                 UpdateGraphicsState(inter, gs);
208             }
209             return static_cast<bool>(h);
210         });
211     }
212     return {};
213 }
214 
IsBlendEnabled() const215 Future<bool> Shader::IsBlendEnabled() const
216 {
217     if (auto inter = GetScene()) {
218         return inter->AddTask([=] {
219             if (auto h = GetGraphicsStateHandle()) {
220                 auto& man = inter->GetRenderContext().GetDevice().GetShaderManager();
221                 auto gs = man.GetGraphicsState(h);
222                 if (gs.colorBlendState.colorAttachmentCount) {
223                     return static_cast<bool>(gs.colorBlendState.colorAttachments[0].enableBlend);
224                 }
225             }
226             return bool {};
227         });
228     }
229     return {};
230 }
231 
EnableBlend(bool enableBlend)232 Future<bool> Shader::EnableBlend(bool enableBlend)
233 {
234     if (auto inter = GetScene()) {
235         return inter->AddTask([=] {
236             auto h = GetGraphicsStateHandle();
237             if (h) {
238                 auto& shaderMgr = inter->GetRenderContext().GetDevice().GetShaderManager();
239                 auto oldgs = shaderMgr.GetGraphicsState(h);
240                 auto renderSlotId = shaderMgr.GetRenderSlotId(
241                     enableBlend ? CORE3D_NS::DefaultMaterialShaderConstants::RENDER_SLOT_FORWARD_TRANSLUCENT
242                                 : CORE3D_NS::DefaultMaterialShaderConstants::RENDER_SLOT_FORWARD_OPAQUE);
243                 auto rsd = shaderMgr.GetRenderSlotData(renderSlotId);
244 
245                 auto gs = shaderMgr.GetGraphicsState(rsd.graphicsState);
246                 gs.rasterizationState.cullModeFlags = oldgs.rasterizationState.cullModeFlags;
247 
248                 if (gs.colorBlendState.colorAttachmentCount == 0) {
249                     gs.colorBlendState.colorAttachmentCount = 1;
250                 }
251                 gs.colorBlendState.colorAttachments[0].enableBlend = enableBlend;
252 
253                 UpdateGraphicsState(inter, gs);
254             }
255             return static_cast<bool>(h);
256         });
257     }
258     return {};
259 }
260 
261 SCENE_END_NAMESPACE()
262