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
37RENDER_BEGIN_NAMESPACE()
38class RenderContext;
39class GpuResourceManager;
40
41class ShaderModule;
42class ComputePipelineStateObject;
43class GpuBuffer;
44class GpuComputeProgram;
45class GpuImage;
46class GpuSampler;
47class GpuResourceManager;
48class GpuComputeProgram;
49class GpuShaderProgram;
50class GraphicsPipelineStateObject;
51class PlatformGpuMemoryAllocator;
52class RenderBackend;
53class RenderFrameSync;
54class NodeContextDescriptorSetManager;
55class NodeContextPoolManager;
56class ShaderModule;
57class Swapchain;
58class GpuSemaphore;
59struct BackendSpecificImageDesc;
60struct GpuAccelerationStructureDesc;
61struct GpuBufferDesc;
62struct GpuComputeProgramCreateData;
63struct GpuImageDesc;
64struct GpuImagePlatformData;
65struct GpuSamplerDesc;
66struct GpuShaderProgramCreateData;
67struct PipelineLayout;
68struct ShaderModuleCreateInfo;
69struct SwapchainCreateInfo;
70
71struct LowLevelRenderPassData {};
72struct LowLevelPipelineLayoutData {};
73
74struct 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
86struct DeviceConstants {
87    static constexpr uint32_t MAX_SWAPCHAIN_COUNT { 8U };
88};
89
90class Device : public IDevice {
91public:
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
251protected:
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
274GpuImageDesc GetImageDescFromHwBufferDesc(uintptr_t platformHwBuffer);
275RENDER_END_NAMESPACE()
276
277#endif // DEVICE_DEVICE_H
278