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_DEVICE_H
17 #define DEVICE_DEVICE_H
18 
19 #include <atomic>
20 #include <cstdint>
21 #include <mutex>
22 
23 #include <base/containers/string.h>
24 #include <base/containers/unique_ptr.h>
25 #include <base/containers/vector.h>
26 #include <base/util/formats.h>
27 #include <core/namespace.h>
28 #include <core/threading/intf_thread_pool.h>
29 #include <render/device/intf_device.h>
30 #include <render/device/pipeline_state_desc.h>
31 #include <render/namespace.h>
32 #include <render/resource_handle.h>
33 
34 #include "device/shader_manager.h"
35 #include "device/swapchain.h"
36 
37 RENDER_BEGIN_NAMESPACE()
38 class RenderContext;
39 class GpuResourceManager;
40 
41 class ShaderModule;
42 class ComputePipelineStateObject;
43 class GpuBuffer;
44 class GpuComputeProgram;
45 class GpuImage;
46 class GpuSampler;
47 class GpuResourceManager;
48 class GpuComputeProgram;
49 class GpuShaderProgram;
50 class GraphicsPipelineStateObject;
51 class PlatformGpuMemoryAllocator;
52 class RenderBackend;
53 class RenderFrameSync;
54 class NodeContextDescriptorSetManager;
55 class NodeContextPoolManager;
56 class ShaderModule;
57 class Swapchain;
58 class GpuSemaphore;
59 struct BackendSpecificImageDesc;
60 struct GpuAccelerationStructureDesc;
61 struct GpuBufferDesc;
62 struct GpuComputeProgramCreateData;
63 struct GpuImageDesc;
64 struct GpuImagePlatformData;
65 struct GpuSamplerDesc;
66 struct GpuShaderProgramCreateData;
67 struct PipelineLayout;
68 struct ShaderModuleCreateInfo;
69 struct SwapchainCreateInfo;
70 
71 struct LowLevelRenderPassData {};
72 struct LowLevelPipelineLayoutData {};
73 
74 struct DeviceFormatSupportConstants {
75     static constexpr uint32_t ALL_FLAGS_SUPPORTED { 0xFFFFu };
76     static constexpr uint32_t LINEAR_FORMAT_MAX_IDX { BASE_NS::Format::BASE_FORMAT_ASTC_12x12_SRGB_BLOCK };
77     static constexpr uint32_t LINEAR_FORMAT_MAX_COUNT { LINEAR_FORMAT_MAX_IDX + 1u };
78     static constexpr uint32_t ADDITIONAL_FORMAT_START_NUMBER { BASE_NS::Format::BASE_FORMAT_G8B8G8R8_422_UNORM };
79     static constexpr uint32_t ADDITIONAL_FORMAT_END_NUMBER { BASE_NS::Format::BASE_FORMAT_G8_B8_R8_3PLANE_444_UNORM };
80     static constexpr uint32_t ADDITIONAL_FORMAT_MAX_COUNT {
81         (ADDITIONAL_FORMAT_END_NUMBER - ADDITIONAL_FORMAT_START_NUMBER) + 1u
82     };
83     static constexpr uint32_t ADDITIONAL_FORMAT_BASE_IDX { LINEAR_FORMAT_MAX_COUNT };
84 };
85 
86 struct DeviceConstants {
87     static constexpr uint32_t MAX_SWAPCHAIN_COUNT { 8U };
88 };
89 
90 class Device : public IDevice {
91 public:
92     Device(RenderContext& renderContext, const DeviceCreateInfo& deviceCreateInfo);
93 
94     Device(const Device&) = delete;
95     Device& operator=(const Device&) = delete;
96 
97     virtual PlatformGpuMemoryAllocator* GetPlatformGpuMemoryAllocator() = 0;
98 
99     // Activate context
100     virtual void Activate() = 0;
101     // Deactivate context
102     virtual void Deactivate() = 0;
103 
104     // Allow parallel render node processing  (on GLES checks that coherent mapping allowed)
105     virtual bool AllowThreadedProcessing() const = 0;
106 
107     // Generally set once to true when device is created.
108     // Set to false e.g. when device is lost.
109     // Set and Get uses atomics if needed by the platform.
110     void SetDeviceStatus(const bool status);
111     bool GetDeviceStatus() const;
112 
113     // (re-)create swapchain
114     void CreateSwapchain(const SwapchainCreateInfo& swapchainCreateInfo) override;
115     RenderHandleReference CreateSwapchainHandle(const SwapchainCreateInfo& swapchainCreateInfo,
116         const RenderHandleReference& replacedHandle, const BASE_NS::string_view name) override;
117     RenderHandleReference CreateSwapchainHandle(const SwapchainCreateInfo& swapchainCreateInfo) override;
118     void DestroySwapchain() override;
119     void DestroySwapchain(const RenderHandleReference& handle) override;
120     // device specific preparation
121     virtual BASE_NS::unique_ptr<Swapchain> CreateDeviceSwapchain(const SwapchainCreateInfo& swapchainCreateInfo) = 0;
122     virtual void DestroyDeviceSwapchain() = 0;
123 
124     RenderHandleReference CreateSwapchainImpl(const SwapchainCreateInfo& swapchainCreateInfo,
125         const RenderHandleReference& replacedHandle, const BASE_NS::string_view name);
126     void DestroySwapchainImpl(const RenderHandleReference& handle);
127 
128     SurfaceTransformFlags GetSurfaceTransformFlags(const RenderHandle& handle) const;
129 
130     // Lock/Unlock access for this frame's GPU resources (for safety reasons)
131     void SetLockResourceBackendAccess(bool value);
132     // Set render backend running
133     void SetRenderBackendRunning(bool value);
134     bool GetLockResourceBackendAccess() const;
135 
136     // Set to true when RenderFrame called
137     // Set to false when coming out of RenderFrame
138     void SetRenderFrameRunning(bool value);
139     bool GetRenderFrameRunning() const;
140 
141     // Marks the beginning of a frame rendering. Expected to at least increment frame counter.
142     void FrameStart();
143     void FrameEnd();
144 
145     IGpuResourceManager& GetGpuResourceManager() const override;
146     IShaderManager& GetShaderManager() const override;
147 
148     void SetBackendConfig(const BackendConfig& config) override;
149 
150     uint64_t GetFrameCount() const override;
151 
152     const CommonDeviceProperties& GetCommonDeviceProperties() const override;
153 
154     DeviceConfiguration GetDeviceConfiguration() const override;
155 
156     bool HasSwapchain() const;
157     // get swapchain with shallow
158     const Swapchain* GetSwapchain(const RenderHandle handle) const;
159 
160     struct SwapchainData {
161         static constexpr uint32_t MAX_IMAGE_VIEW_COUNT { 5U };
162 
163         RenderHandle remappableSwapchainImage {};
164         RenderHandle imageViews[MAX_IMAGE_VIEW_COUNT];
165         uint32_t imageViewCount { 0U };
166     };
167 
168     struct InternalSwapchainData {
169         static constexpr uint32_t MAX_IMAGE_VIEW_COUNT { 5U };
170 
171         uint64_t surfaceHandle { 0 };
172         uintptr_t window { 0 };
173 
174         BASE_NS::string globalName;
175         BASE_NS::string name;
176         RenderHandleReference remappableSwapchainImage {};
177         RenderHandleReference additionalDepthBufferHandle {};
178         RenderHandle remappableAdditionalSwapchainImage {}; // Not owned
179         RenderHandleReference imageViews[MAX_IMAGE_VIEW_COUNT];
180         uint32_t imageViewCount { 0U };
181 
182         BASE_NS::unique_ptr<Swapchain> swapchain;
183     };
184     SwapchainData GetSwapchainData(const RenderHandle handle) const;
185 
186     // Number of command buffers to allocate for each node
187     uint32_t GetCommandBufferingCount() const;
188     // Get ANDed memory property flags from all memory pools
189     MemoryPropertyFlags GetSharedMemoryPropertyFlags() const;
190 
191     BASE_NS::Format GetFormatOrFallback(BASE_NS::Format format) const;
192 
193     // Platform specific creation
194 
195     virtual BASE_NS::unique_ptr<GpuBuffer> CreateGpuBuffer(const GpuBufferDesc& desc) = 0;
196     virtual BASE_NS::unique_ptr<GpuBuffer> CreateGpuBuffer(const GpuAccelerationStructureDesc& desc) = 0;
197 
198     // Create gpu image resources
199     virtual BASE_NS::unique_ptr<GpuImage> CreateGpuImage(const GpuImageDesc& desc) = 0;
200     /** Creates a engine GpuImage resource with platform resources.
201      * Does not own the platform resources nor does not destroy them.
202      */
203     virtual BASE_NS::unique_ptr<GpuImage> CreateGpuImageView(
204         const GpuImageDesc& desc, const GpuImagePlatformData& platformData) = 0;
205     virtual BASE_NS::unique_ptr<GpuImage> CreateGpuImageView(
206         const GpuImageDesc& desc, const BackendSpecificImageDesc& platformData) = 0;
207     virtual BASE_NS::vector<BASE_NS::unique_ptr<GpuImage>> CreateGpuImageViews(const Swapchain& platformData) = 0;
208 
209     virtual BASE_NS::unique_ptr<GpuSampler> CreateGpuSampler(const GpuSamplerDesc& desc) = 0;
210 
211     virtual BASE_NS::unique_ptr<RenderFrameSync> CreateRenderFrameSync() = 0;
212     virtual BASE_NS::unique_ptr<RenderBackend> CreateRenderBackend(
213         GpuResourceManager& gpuResourceMgr, const CORE_NS::IParallelTaskQueue::Ptr& queue) = 0;
214 
215     virtual BASE_NS::unique_ptr<ShaderModule> CreateShaderModule(const ShaderModuleCreateInfo& data) = 0;
216     virtual BASE_NS::unique_ptr<ShaderModule> CreateComputeShaderModule(const ShaderModuleCreateInfo& data) = 0;
217     virtual BASE_NS::unique_ptr<GpuShaderProgram> CreateGpuShaderProgram(GpuShaderProgramCreateData const& data) = 0;
218     virtual BASE_NS::unique_ptr<GpuComputeProgram> CreateGpuComputeProgram(GpuComputeProgramCreateData const& data) = 0;
219 
220     virtual BASE_NS::unique_ptr<NodeContextDescriptorSetManager> CreateNodeContextDescriptorSetManager() = 0;
221     virtual BASE_NS::unique_ptr<NodeContextPoolManager> CreateNodeContextPoolManager(
222         class GpuResourceManager& gpuResourceMgr, const GpuQueue& gpuQueue) = 0;
223 
224     virtual BASE_NS::unique_ptr<GraphicsPipelineStateObject> CreateGraphicsPipelineStateObject(
225         const GpuShaderProgram& gpuProgram, const GraphicsState& graphicsState, const PipelineLayout& pipelineLayout,
226         const VertexInputDeclarationView& vertexInputDeclarationView,
227         const ShaderSpecializationConstantDataView& shaderSpecializationConstantDataView,
228         const BASE_NS::array_view<const DynamicStateEnum> dynamicStates, const RenderPassDesc& renderPassDesc,
229         const BASE_NS::array_view<const RenderPassSubpassDesc>& renderPassSubpassDesc, const uint32_t subpassIndex,
230         const LowLevelRenderPassData* renderPassData, const LowLevelPipelineLayoutData* pipelineLayoutData) = 0;
231 
232     virtual BASE_NS::unique_ptr<ComputePipelineStateObject> CreateComputePipelineStateObject(
233         const GpuComputeProgram& gpuProgram, const PipelineLayout& pipelineLayout,
234         const ShaderSpecializationConstantDataView& shaderSpecializationConstantDataView,
235         const LowLevelPipelineLayoutData* pipelineLayoutData) = 0;
236 
237     virtual BASE_NS::unique_ptr<GpuSemaphore> CreateGpuSemaphore() = 0;
238     virtual BASE_NS::unique_ptr<GpuSemaphore> CreateGpuSemaphoreView(const uint64_t handle) = 0;
239 
240     // returns a valid queue from the same family or default queue
241     virtual GpuQueue GetValidGpuQueue(const GpuQueue& gpuQueue) const = 0;
242     virtual uint32_t GetGpuQueueCount() const = 0;
243 
244     /** Initialize cache for accelerating pipeline state object creation. Caching is not used unless this function is
245      * called.
246      * @param initialData Optional cache content returned by GetPipelineCache.
247      */
248     virtual void InitializePipelineCache(BASE_NS::array_view<const uint8_t> initialData) = 0;
249     virtual BASE_NS::vector<uint8_t> GetPipelineCache() const = 0;
250 
251 protected:
252     RenderContext& renderContext_;
253     DeviceConfiguration deviceConfiguration_;
254 
255     BASE_NS::unique_ptr<GpuResourceManager> gpuResourceMgr_;
256     BASE_NS::unique_ptr<ShaderManager> shaderMgr_;
257 
258     // multi-swapchain, the built-in default is only with swapchain_ and swapchainData_
259     BASE_NS::vector<InternalSwapchainData> swapchains_;
260     RenderHandleReference defaultSwapchainHandle_;
261 
262     std::atomic<bool> deviceStatus_ { false };
263     uint64_t frameCount_ { 0 };
264 
265     bool isRenderbackendRunning_ { false };
266     bool isBackendResourceAccessLocked_ { false };
267     bool isRenderFrameRunning_ { false };
268 
269     MemoryPropertyFlags deviceSharedMemoryPropertyFlags_ { 0 };
270     CommonDeviceProperties commonDeviceProperties_;
271 };
272 
273 // Plaform specific helper
274 GpuImageDesc GetImageDescFromHwBufferDesc(uintptr_t platformHwBuffer);
275 RENDER_END_NAMESPACE()
276 
277 #endif // DEVICE_DEVICE_H
278