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 #ifndef DEVICE_SHADER_MANAGER_H
17 #define DEVICE_SHADER_MANAGER_H
18 
19 #include <atomic>
20 #include <mutex>
21 
22 #include <base/containers/array_view.h>
23 #include <base/containers/fixed_string.h>
24 #include <base/containers/string.h>
25 #include <base/containers/string_view.h>
26 #include <base/containers/unique_ptr.h>
27 #include <base/containers/unordered_map.h>
28 #include <base/containers/vector.h>
29 #include <base/math/vector.h>
30 #include <core/namespace.h>
31 #include <render/device/gpu_resource_desc.h>
32 #include <render/device/intf_shader_manager.h>
33 #include <render/device/pipeline_layout_desc.h>
34 #include <render/device/pipeline_state_desc.h>
35 #include <render/namespace.h>
36 #include <render/resource_handle.h>
37 
38 #include "device/gpu_program.h"
39 #include "device/gpu_resource_handle_util.h" // for hash<RenderHandle>
40 
41 CORE_BEGIN_NAMESPACE()
42 class IFileManager;
43 CORE_END_NAMESPACE()
44 RENDER_BEGIN_NAMESPACE()
45 class Device;
46 class ShaderModule;
47 class ShaderLoader;
48 
49 constexpr const uint32_t INVALID_SM_INDEX { ~0u };
50 
51 struct ComputeShaderCreateData {
52     BASE_NS::string_view path;
53     uint32_t renderSlotId { INVALID_SM_INDEX };
54     uint32_t categoryId { INVALID_SM_INDEX };
55     uint32_t pipelineLayoutIndex { INVALID_SM_INDEX };
56     uint32_t shaderModuleIndex { INVALID_SM_INDEX };
57 
58     BASE_NS::string_view shaderFileStr;
59     BASE_NS::string_view materialMetadata;
60 };
61 
62 struct ShaderCreateData {
63     BASE_NS::string_view path;
64     uint32_t renderSlotId { INVALID_SM_INDEX };
65     uint32_t categoryId { INVALID_SM_INDEX };
66     uint32_t vertexInputDeclarationIndex { INVALID_SM_INDEX };
67     uint32_t pipelineLayoutIndex { INVALID_SM_INDEX };
68     uint32_t graphicsStateIndex { INVALID_SM_INDEX };
69 
70     uint32_t vertShaderModuleIndex { INVALID_SM_INDEX };
71     uint32_t fragShaderModuleIndex { INVALID_SM_INDEX };
72 
73     BASE_NS::string_view shaderFileStr;
74     BASE_NS::string_view materialMetadata;
75 };
76 
77 struct ShaderReflectionData {
78     BASE_NS::array_view<const uint8_t> reflectionData;
79 
80     bool IsValid() const;
81     ShaderStageFlags GetStageFlags() const;
82     PipelineLayout GetPipelineLayout() const;
83     BASE_NS::vector<ShaderSpecialization::Constant> GetSpecializationConstants() const;
84     BASE_NS::vector<VertexInputDeclaration::VertexInputAttributeDescription> GetInputDescriptions() const;
85     BASE_NS::Math::UVec3 GetLocalSize() const;
86 
87     const uint8_t* GetPushConstants() const;
88 };
89 
90 struct ShaderModuleCreateInfo {
91     ShaderStageFlags shaderStageFlags;
92     BASE_NS::array_view<const uint8_t> spvData;
93     ShaderReflectionData reflectionData;
94 };
95 
96 // Ref counted shaders are really not needed
97 // For API consistency the same RenderHandleReference is used, but the counter is dummy
98 class ShaderReferenceCounter final : public IRenderReferenceCounter {
99 public:
100     ShaderReferenceCounter() = default;
101     ~ShaderReferenceCounter() override = default;
102 
103     ShaderReferenceCounter(const ShaderReferenceCounter&) = delete;
104     ShaderReferenceCounter& operator=(const ShaderReferenceCounter&) = delete;
105 
Ref()106     void Ref() override
107     {
108         refcnt_.fetch_add(1, std::memory_order_relaxed);
109     };
110 
Unref()111     void Unref() override
112     {
113         if (std::atomic_fetch_sub_explicit(&refcnt_, 1, std::memory_order_release) == 1) {
114             std::atomic_thread_fence(std::memory_order_acquire);
115             delete this;
116         }
117     };
118 
GetRefCount()119     int32_t GetRefCount() const override
120     {
121         // NOTE: not destroyed based on ref count
122         // the manager is always holding the reference
123         // basically plugins could hold their shader data handles and release
124         return 1;
125     };
126 
127 private:
128     std::atomic<int32_t> refcnt_ { 0 };
129 };
130 
131 /* ShaderManager implementation.
132 Not internally synchronized. */
133 class ShaderManager final : public IShaderManager {
134 public:
135     static constexpr uint32_t MAX_DEFAULT_NAME_LENGTH { 128 };
136 
137     explicit ShaderManager(Device& device);
138     ~ShaderManager() override;
139 
140     RenderHandleReference Get(const RenderHandle& handle) const override;
141     RenderHandleReference CreateComputeShader(const ComputeShaderCreateInfo& createInfo) override;
142     RenderHandleReference CreateComputeShader(const ComputeShaderCreateInfo& createInfo,
143         const BASE_NS::string_view baseShaderPath, const BASE_NS::string_view variantName) override;
144     RenderHandleReference CreateShader(const ShaderCreateInfo& createInfo) override;
145     RenderHandleReference CreateShader(const ShaderCreateInfo& createInfo, const BASE_NS::string_view baseShaderPath,
146         const BASE_NS::string_view variantName) override;
147 
148     RenderHandleReference CreateVertexInputDeclaration(const VertexInputDeclarationCreateInfo& createInfo) override;
149     RenderHandleReference CreatePipelineLayout(const PipelineLayoutCreateInfo& createInfo) override;
150     RenderHandleReference CreateGraphicsState(const GraphicsStateCreateInfo& createInfo) override;
151     RenderHandleReference CreateGraphicsState(
152         const GraphicsStateCreateInfo& createInfo, const GraphicsStateVariantCreateInfo& variantCreateInfo) override;
153 
154     uint32_t CreateRenderSlotId(const BASE_NS::string_view renderSlot) override;
155     void SetRenderSlotData(const uint32_t renderSlotId, const RenderHandleReference& shaderHandle,
156         const RenderHandleReference& stateHandle) override;
157 
158     uint32_t CreateCategoryId(const BASE_NS::string_view category);
159 
160     RenderHandleReference GetShaderHandle(const BASE_NS::string_view path) const override;
161     RenderHandleReference GetShaderHandle(
162         const BASE_NS::string_view path, const BASE_NS::string_view variantName) const override;
163     RenderHandleReference GetShaderHandle(
164         const RenderHandleReference& handle, const uint32_t renderSlotId) const override;
165     RenderHandleReference GetShaderHandle(const RenderHandle& handle, const uint32_t renderSlotId) const;
166     BASE_NS::vector<RenderHandleReference> GetShaders(const uint32_t renderSlotId) const override;
167     BASE_NS::vector<RenderHandle> GetShaderRawHandles(const uint32_t renderSlotId) const;
168 
169     RenderHandleReference GetGraphicsStateHandle(const BASE_NS::string_view path) const override;
170     RenderHandleReference GetGraphicsStateHandle(
171         const BASE_NS::string_view path, const BASE_NS::string_view variantName) const override;
172     RenderHandleReference GetGraphicsStateHandle(
173         const RenderHandleReference& handle, const uint32_t renderSlotId) const override;
174     RenderHandleReference GetGraphicsStateHandle(const RenderHandle& handle, const uint32_t renderSlotId) const;
175     RenderHandleReference GetGraphicsStateHandleByHash(const uint64_t hash) const override;
176     RenderHandleReference GetGraphicsStateHandleByShaderHandle(const RenderHandleReference& handle) const override;
177     RenderHandleReference GetGraphicsStateHandleByShaderHandle(const RenderHandle& handle) const;
178     GraphicsState GetGraphicsState(const RenderHandleReference& handle) const override;
179     const GraphicsState& GetGraphicsStateRef(const RenderHandleReference& handle) const;
180     const GraphicsState& GetGraphicsStateRef(const RenderHandle& handle) const;
181     BASE_NS::vector<RenderHandleReference> GetGraphicsStates(const uint32_t renderSlotId) const override;
182 
183     uint32_t GetRenderSlotId(const BASE_NS::string_view renderSlot) const override;
184     uint32_t GetRenderSlotId(const RenderHandleReference& handle) const override;
185     uint32_t GetRenderSlotId(const RenderHandle& handle) const;
186     RenderSlotData GetRenderSlotData(const uint32_t renderSlotId) const override;
187     BASE_NS::string GetRenderSlotName(const uint32_t renderSlotId) const override;
188 
189     RenderHandleReference GetVertexInputDeclarationHandleByShaderHandle(
190         const RenderHandleReference& handle) const override;
191     RenderHandleReference GetVertexInputDeclarationHandleByShaderHandle(const RenderHandle& handle) const;
192     RenderHandleReference GetVertexInputDeclarationHandle(const BASE_NS::string_view path) const override;
193     VertexInputDeclarationView GetVertexInputDeclarationView(const RenderHandleReference& handle) const override;
194     VertexInputDeclarationView GetVertexInputDeclarationView(const RenderHandle& handle) const;
195 
196     RenderHandleReference GetPipelineLayoutHandleByShaderHandle(const RenderHandleReference& handle) const override;
197     RenderHandleReference GetPipelineLayoutHandleByShaderHandle(const RenderHandle& handle) const;
198 
199     RenderHandleReference GetPipelineLayoutHandle(const BASE_NS::string_view path) const override;
200     PipelineLayout GetPipelineLayout(const RenderHandleReference& handle) const override;
201     PipelineLayout GetPipelineLayout(const RenderHandle& handle) const;
202     const PipelineLayout& GetPipelineLayoutRef(const RenderHandle& handle) const;
203 
204     RenderHandleReference GetReflectionPipelineLayoutHandle(const RenderHandle& handle) const;
205     RenderHandleReference GetReflectionPipelineLayoutHandle(const RenderHandleReference& handle) const override;
206     PipelineLayout GetReflectionPipelineLayout(const RenderHandleReference& handle) const override;
207     const PipelineLayout& GetReflectionPipelineLayoutRef(const RenderHandle& handle) const;
208     ShaderSpecializationConstantView GetReflectionSpecialization(const RenderHandleReference& handle) const override;
209     ShaderSpecializationConstantView GetReflectionSpecialization(const RenderHandle& handle) const;
210     VertexInputDeclarationView GetReflectionVertexInputDeclaration(const RenderHandleReference& handle) const override;
211     VertexInputDeclarationView GetReflectionVertexInputDeclaration(const RenderHandle& handle) const;
212     ShaderThreadGroup GetReflectionThreadGroupSize(const RenderHandleReference& handle) const override;
213     ShaderThreadGroup GetReflectionThreadGroupSize(const RenderHandle& handle) const;
214 
215     uint64_t HashGraphicsState(const GraphicsState& graphicsState) const override;
216 
217     struct ShaderPathCreateData {
218         const BASE_NS::string_view baseShaderPath;
219         const BASE_NS::string_view variantName;
220         const BASE_NS::string_view displayName;
221     };
222     RenderHandleReference Create(const ComputeShaderCreateData& createInfo, const ShaderPathCreateData& pathCreateInfo);
223     RenderHandleReference Create(const ShaderCreateData& createInfo, const ShaderPathCreateData& pathCreateInfo);
224     // NOTE: Can be used to add additional base uri name for a shader which has variant names
225     void AddAdditionalNameForHandle(const RenderHandleReference& handle, const BASE_NS::string_view path);
226 
227     const GpuComputeProgram* GetGpuComputeProgram(const RenderHandle& gpuHandle) const;
228     const GpuShaderProgram* GetGpuShaderProgram(const RenderHandle& gpuHandle) const;
229 
230     void HandlePendingAllocations();
231 
232     // replaces if already found
233     uint32_t CreateShaderModule(const BASE_NS::string_view path, const ShaderModuleCreateInfo& createInfo);
234     // returns null if not found (i.e. needs to be created)
235     ShaderModule* GetShaderModule(const uint32_t index) const;
236     // returns ~0u if not found (i.e. needs to be created)
237     uint32_t GetShaderModuleIndex(const BASE_NS::string_view path) const;
238 
239     bool IsComputeShader(const RenderHandleReference& handle) const override;
240     bool IsShader(const RenderHandleReference& handle) const override;
241 
242     void LoadShaderFiles(const ShaderFilePathDesc& desc) override;
243     void LoadShaderFile(const BASE_NS::string_view uri) override;
244     void ReloadShaderFile(const BASE_NS::string_view uri) override;
245     void UnloadShaderFiles(const ShaderFilePathDesc& desc) override;
246 
247     const BASE_NS::string_view GetShaderFile(const RenderHandleReference& handle) const override;
248     const CORE_NS::json::value* GetMaterialMetadata(const RenderHandleReference& handle) const override;
249 
250     void Destroy(const RenderHandleReference& handle) override;
251 
252     BASE_NS::vector<RenderHandleReference> GetShaders(
253         const RenderHandleReference& handle, const ShaderStageFlags shaderStageFlags) const override;
254     BASE_NS::vector<RenderHandle> GetShaders(const RenderHandle& handle, const ShaderStageFlags shaderStageFlags) const;
255 
256     BASE_NS::vector<RenderHandleReference> GetShaders() const override;
257     BASE_NS::vector<RenderHandleReference> GetGraphicsStates() const override;
258     BASE_NS::vector<RenderHandleReference> GetPipelineLayouts() const override;
259     BASE_NS::vector<RenderHandleReference> GetVertexInputDeclarations() const override;
260 
261     IdDesc GetIdDesc(const RenderHandleReference& handle) const override;
262     uint64_t GetFrameIndex(const RenderHandleReference& handle) const override;
263 
264     IShaderPipelineBinder::Ptr CreateShaderPipelineBinder(const RenderHandleReference& handle) const override;
265     IShaderPipelineBinder::Ptr CreateShaderPipelineBinder(
266         const RenderHandleReference& handle, const RenderHandleReference& plHandle) const override;
267     IShaderPipelineBinder::Ptr CreateShaderPipelineBinder(
268         const RenderHandleReference& handle, const PipelineLayout& pipelineLayout) const override;
269 
270     CompatibilityFlags GetCompatibilityFlags(const RenderHandle& lhs, const RenderHandle& rhs) const;
271     CompatibilityFlags GetCompatibilityFlags(
272         const RenderHandleReference& lhs, const RenderHandleReference& rhs) const override;
273 
274     GraphicsStateFlags GetForcedGraphicsStateFlags(const RenderHandle& handle) const;
275     GraphicsStateFlags GetForcedGraphicsStateFlags(const RenderHandleReference& handle) const override;
276     GraphicsStateFlags GetForcedGraphicsStateFlags(const uint32_t renderSlotId) const override;
277 
278     // set (engine) file manager to be usable with shader loading with shader manager api
279     void SetFileManager(CORE_NS::IFileManager& fileMgr);
280     bool HasReloadedShaderForBackend() const;
281     BASE_NS::array_view<const RenderHandle> GetReloadedShadersForBackend() const;
282 
283     struct ShaderNameData {
284         BASE_NS::fixed_string<MAX_DEFAULT_NAME_LENGTH> path;
285         BASE_NS::fixed_string<MAX_DEFAULT_NAME_LENGTH> variantName;
286         BASE_NS::fixed_string<MAX_DEFAULT_NAME_LENGTH> displayName;
287     };
288     struct ComputeMappings {
289         struct Data {
290             RenderHandleReference rhr;
291             RenderHandle baseShaderHandle; // provides a link to find related shaders
292 
293             uint32_t renderSlotId { INVALID_SM_INDEX };
294             uint32_t pipelineLayoutIndex { INVALID_SM_INDEX };
295             uint32_t reflectionPipelineLayoutIndex { INVALID_SM_INDEX };
296             uint32_t categoryId { INVALID_SM_INDEX };
297 
298             uint64_t frameIndex { 0 };
299         };
300         BASE_NS::vector<Data> clientData;
301         BASE_NS::vector<ShaderNameData> nameData;
302     };
303     struct GraphicsMappings {
304         struct Data {
305             RenderHandleReference rhr;
306             RenderHandle baseShaderHandle; // provides a link to find related shaders
307 
308             uint32_t renderSlotId { INVALID_SM_INDEX };
309             uint32_t pipelineLayoutIndex { INVALID_SM_INDEX };
310             uint32_t reflectionPipelineLayoutIndex { INVALID_SM_INDEX };
311 
312             uint32_t vertexInputDeclarationIndex { INVALID_SM_INDEX };
313             uint32_t graphicsStateIndex { INVALID_SM_INDEX };
314 
315             uint32_t categoryId { INVALID_SM_INDEX };
316 
317             uint64_t frameIndex { 0 };
318         };
319         BASE_NS::vector<Data> clientData;
320         BASE_NS::vector<ShaderNameData> nameData;
321     };
322     struct GraphicsStateData {
323         struct Indices {
324             uint64_t hash { 0 };
325             uint32_t renderSlotId { INVALID_SM_INDEX };
326             uint32_t baseVariantIndex { INVALID_SM_INDEX };
327             // forced state flags
328             GraphicsStateFlags stateFlags { 0u };
329         };
330         BASE_NS::vector<RenderHandleReference> rhr;
331         BASE_NS::vector<GraphicsState> graphicsStates;
332         BASE_NS::vector<Indices> data;
333 
334         BASE_NS::unordered_map<BASE_NS::string, uint32_t> nameToIndex;
335         BASE_NS::unordered_map<uint64_t, uint32_t> hashToIndex;
336         // hash based on base graphics state handle and render slot id
337         BASE_NS::unordered_map<uint64_t, uint32_t> variantHashToIndex;
338     };
339 
340 private:
341     Device& device_;
342     CORE_NS::IFileManager* fileMgr_ { nullptr }; // engine file manager to be used with shader loading from API
343     BASE_NS::unique_ptr<ShaderLoader> shaderLoader_;
344 
345     // for all shaders, names are unique
346     BASE_NS::unordered_map<BASE_NS::string, RenderHandle> nameToClientHandle_;
347     // hash based on base shader handle id and render slot id
348     BASE_NS::unordered_map<uint64_t, RenderHandle> hashToShaderVariant_;
349     ComputeMappings computeShaderMappings_;
350     GraphicsMappings shaderMappings_;
351 
352     struct ClientDataIndices {
353         uint32_t renderSlotIndex { INVALID_SM_INDEX };
354         uint32_t pipelineLayoutIndex { INVALID_SM_INDEX };
355         uint32_t reflectionPipelineLayoutIndex { INVALID_SM_INDEX };
356         uint32_t categoryIndex { INVALID_SM_INDEX };
357     };
358     RenderHandle CreateClientData(
359         const BASE_NS::string_view path, const RenderHandleType type, const ClientDataIndices& cdi);
360 
361     void DestroyShader(const RenderHandle handle);
362     void DestroyGraphicsState(const RenderHandle handle);
363     void DestroyPipelineLayout(const RenderHandle handle);
364     void DestroyVertexInputDeclaration(const RenderHandle handle);
365 
366     IdDesc GetShaderIdDesc(const RenderHandle handle) const;
367     uint64_t GetShaderFrameIndex(const RenderHandle handle) const;
368 
369     BASE_NS::string GetCategoryName(const uint32_t categoryId) const;
370 
371     // NOTE: ATM GpuComputeProgram and GpuShaderPrograms are currently re-created for every new shader created
372     // will be stored and re-used in the future
373 
374     struct ComputeShaderData {
375         BASE_NS::unique_ptr<GpuComputeProgram> gsp;
376         uint32_t pipelineLayoutIndex { INVALID_SM_INDEX };
377         uint32_t compModuleIndex { INVALID_SM_INDEX };
378     };
379     BASE_NS::vector<ComputeShaderData> computeShaders_;
380 
381     struct ShaderData {
382         BASE_NS::unique_ptr<GpuShaderProgram> gsp;
383         uint32_t pipelineLayoutIndex { INVALID_SM_INDEX };
384         uint32_t vertexInputDeclIndex { INVALID_SM_INDEX };
385 
386         uint32_t vertModuleIndex { INVALID_SM_INDEX };
387         uint32_t fragModuleIndex { INVALID_SM_INDEX };
388     };
389     BASE_NS::vector<ShaderData> shaders_;
390 
391     struct RenderSlotIds {
392         BASE_NS::vector<RenderSlotData> data;
393         BASE_NS::unordered_map<BASE_NS::string, uint32_t> nameToId;
394     };
395     RenderSlotIds renderSlotIds_;
396 
397     struct Category {
398         BASE_NS::vector<BASE_NS::string> data;
399         BASE_NS::unordered_map<BASE_NS::string, uint32_t> nameToId;
400     };
401     Category category_;
402 
403     struct ComputeShaderAllocs {
404         RenderHandle handle;
405         uint32_t computeModuleIndex { INVALID_SM_INDEX };
406         uint32_t pipelineLayoutIndex { INVALID_SM_INDEX };
407     };
408     struct ShaderAllocs {
409         RenderHandle handle;
410         uint32_t vertModuleIndex { INVALID_SM_INDEX };
411         uint32_t fragModuleIndex { INVALID_SM_INDEX };
412         uint32_t pipelineLayoutIndex { INVALID_SM_INDEX };
413         uint32_t vertexInputDeclIndex { INVALID_SM_INDEX };
414     };
415     struct Allocs {
416         // client handle, object
417         BASE_NS::vector<ComputeShaderAllocs> computeShaders;
418         BASE_NS::vector<ShaderAllocs> shaders;
419         BASE_NS::vector<uint32_t> recreatedComputeModuleIndices;
420         BASE_NS::vector<uint32_t> recreatedShaderModuleIndices;
421 
422         BASE_NS::vector<RenderHandle> destroyHandles;
423     };
424     Allocs pendingAllocations_;
425     // locks only pending allocations data
426     std::mutex pendingMutex_;
427 
428     void HandlePendingShaders(Allocs& allocs);
429     void HandlePendingModules(Allocs& allocs);
430 
431     struct DeferredDestructions {
432         struct Module {
433             uint64_t frameIndex { 0 };
434             BASE_NS::unique_ptr<ShaderModule> shaderModule;
435         };
436         struct ComputeProgram {
437             uint64_t frameIndex { 0 };
438             BASE_NS::unique_ptr<GpuComputeProgram> computeProgram;
439         };
440         struct ShaderProgram {
441             uint64_t frameIndex { 0 };
442             BASE_NS::unique_ptr<GpuShaderProgram> shaderProgram;
443         };
444         BASE_NS::vector<Module> shaderModules;
445         BASE_NS::vector<ComputeProgram> computePrograms;
446         BASE_NS::vector<ShaderProgram> shaderPrograms;
447     };
448     DeferredDestructions deferredDestructions_;
449 
450     struct PL {
451         BASE_NS::vector<RenderHandleReference> rhr;
452         BASE_NS::vector<PipelineLayout> data;
453         BASE_NS::unordered_map<BASE_NS::string, uint32_t> nameToIndex;
454 
455         BASE_NS::unordered_map<RenderHandle, uint32_t> computeShaderToIndex;
456         BASE_NS::unordered_map<RenderHandle, uint32_t> shaderToIndex;
457     };
458     struct VID {
459         BASE_NS::vector<RenderHandleReference> rhr;
460         BASE_NS::vector<VertexInputDeclarationData> data;
461         BASE_NS::unordered_map<BASE_NS::string, uint32_t> nameToIndex;
462         BASE_NS::unordered_map<RenderHandle, uint32_t> shaderToIndex;
463     };
464     VID shaderVid_;
465     PL pl_;
466 
467     GraphicsStateData graphicsStates_;
468 
469     struct ShaderModules {
470         BASE_NS::vector<BASE_NS::unique_ptr<ShaderModule>> shaderModules;
471         BASE_NS::unordered_map<BASE_NS::string, uint32_t> nameToIndex;
472     };
473     ShaderModules shaderModules_;
474 
475     PipelineLayout defaultPipelineLayout_;
476     ComputeShaderReflection defaultComputeShaderReflection_;
477     ShaderReflection defaultShaderReflection_;
478     GraphicsState defaultGraphicsState_;
479     ShaderSpecializationConstantView defaultSSCV_;
480     VertexInputDeclarationView defaultVIDV_;
481     ShaderThreadGroup defaultSTG_;
482 
483     struct MaterialMetadata {
484         BASE_NS::string raw;
485         CORE_NS::json::value json;
486     };
487     BASE_NS::unordered_map<RenderHandle, MaterialMetadata> shaderToMetadata_;
488     BASE_NS::unordered_map<RenderHandle, BASE_NS::string> handleToShaderDataFile_;
489 
490     BASE_NS::vector<RenderHandle> reloadedShaders_;
491     BASE_NS::vector<RenderHandle> reloadedShadersForBackend_;
492 };
493 
494 class RenderNodeShaderManager final : public IRenderNodeShaderManager {
495 public:
496     explicit RenderNodeShaderManager(const ShaderManager& shaderMgr);
497     ~RenderNodeShaderManager() = default;
498 
499     RenderHandle GetShaderHandle(const BASE_NS::string_view path) const override;
500     RenderHandle GetShaderHandle(
501         const BASE_NS::string_view path, const BASE_NS::string_view variantName) const override;
502     RenderHandle GetShaderHandle(const RenderHandle& name, const uint32_t renderSlotId) const override;
503     BASE_NS::vector<RenderHandle> GetShaders(const uint32_t renderSlotId) const override;
504 
505     RenderHandle GetGraphicsStateHandle(const BASE_NS::string_view path) const override;
506     RenderHandle GetGraphicsStateHandle(
507         const BASE_NS::string_view path, const BASE_NS::string_view variantName) const override;
508     RenderHandle GetGraphicsStateHandle(const RenderHandle& handle, const uint32_t renderSlotId) const override;
509     RenderHandle GetGraphicsStateHandleByHash(const uint64_t hash) const override;
510     RenderHandle GetGraphicsStateHandleByShaderHandle(const RenderHandle& handle) const override;
511     virtual const GraphicsState& GetGraphicsState(const RenderHandle& handle) const override;
512 
513     uint32_t GetRenderSlotId(const BASE_NS::string_view renderSlot) const override;
514     uint32_t GetRenderSlotId(const RenderHandle& handle) const override;
515     IShaderManager::RenderSlotData GetRenderSlotData(const uint32_t renderSlotId) const override;
516 
517     RenderHandle GetVertexInputDeclarationHandleByShaderHandle(const RenderHandle& handle) const override;
518     RenderHandle GetVertexInputDeclarationHandle(const BASE_NS::string_view path) const override;
519     VertexInputDeclarationView GetVertexInputDeclarationView(const RenderHandle& handle) const override;
520 
521     RenderHandle GetPipelineLayoutHandleByShaderHandle(const RenderHandle& handle) const override;
522     const PipelineLayout& GetPipelineLayout(const RenderHandle& handle) const override;
523     RenderHandle GetPipelineLayoutHandle(const BASE_NS::string_view path) const override;
524 
525     RenderHandle GetReflectionPipelineLayoutHandle(const RenderHandle& handle) const override;
526     const PipelineLayout& GetReflectionPipelineLayout(const RenderHandle& handle) const override;
527     ShaderSpecializationConstantView GetReflectionSpecialization(const RenderHandle& handle) const override;
528     VertexInputDeclarationView GetReflectionVertexInputDeclaration(const RenderHandle& handle) const override;
529     ShaderThreadGroup GetReflectionThreadGroupSize(const RenderHandle& handle) const override;
530 
531     uint64_t HashGraphicsState(const GraphicsState& graphicsState) const override;
532 
533     bool IsValid(const RenderHandle& handle) const override;
534     bool IsComputeShader(const RenderHandle& handle) const override;
535     bool IsShader(const RenderHandle& handle) const override;
536 
537     BASE_NS::vector<RenderHandle> GetShaders(
538         const RenderHandle& handle, const ShaderStageFlags shaderStageFlags) const override;
539 
540     IShaderManager::CompatibilityFlags GetCompatibilityFlags(
541         const RenderHandle& lhs, const RenderHandle& rhs) const override;
542 
543     GraphicsStateFlags GetForcedGraphicsStateFlags(const RenderHandle& handle) const override;
544     GraphicsStateFlags GetForcedGraphicsStateFlags(const uint32_t renderSlotId) const override;
545 
546 private:
547     const ShaderManager& shaderMgr_;
548 };
549 RENDER_END_NAMESPACE()
550 
551 #endif // DEVICE_SHADER_MANAGER_H
552