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 GLES_DEVICE_GLES_H
17 #define GLES_DEVICE_GLES_H
18 
19 #include <cstddef>
20 #include <cstdint>
21 #include <mutex>
22 
23 #include <base/containers/string_view.h>
24 #include <base/containers/unique_ptr.h>
25 #include <base/containers/vector.h>
26 #include <base/math/vector.h>
27 #include <base/namespace.h>
28 #include <render/device/pipeline_state_desc.h>
29 #include <render/gles/intf_device_gles.h>
30 #include <render/namespace.h>
31 #include <render/resource_handle.h>
32 
33 #include "device/device.h"
34 #include "gles/swapchain_gles.h"
35 
36 #if RENDER_HAS_GLES_BACKEND
37 #include "egl_state.h"
38 #endif
39 #if RENDER_HAS_GL_BACKEND
40 #include "wgl_state.h"
41 #endif
42 
43 RENDER_BEGIN_NAMESPACE()
44 class ComputePipelineStateObject;
45 class GpuBuffer;
46 class GpuComputeProgram;
47 class GpuImage;
48 class GpuResourceManager;
49 class GpuSemaphore;
50 class GpuSampler;
51 class GpuShaderProgram;
52 class GraphicsPipelineStateObject;
53 class LowLevelDeviceGLES;
54 class NodeContextDescriptorSetManager;
55 class NodeContextPoolManager;
56 class RenderBackend;
57 class RenderFrameSync;
58 class PlatformGpuMemoryAllocator;
59 class ShaderManager;
60 class Swapchain;
61 class SwapchainGLES;
62 
63 struct BackendSpecificImageDesc;
64 struct GpuAccelerationStructureDesc;
65 struct GpuBufferDesc;
66 struct GpuComputeProgramCreateData;
67 struct GpuImageDesc;
68 struct GpuImagePlatformData;
69 struct GpuSamplerDesc;
70 struct GpuShaderProgramCreateData;
71 struct SwapchainCreateInfo;
72 struct PipelineLayout;
73 
74 class DeviceGLES final : public Device {
75 public:
76     // NOTE: normalized flag
77     struct ImageFormat {
78         BASE_NS::Format coreFormat;
79         uint32_t format;
80         uint32_t internalFormat;
81         uint32_t dataType;
82         uint32_t bytesperpixel;
83         struct {
84             bool compressed;
85             uint8_t blockW;
86             uint8_t blockH;
87             uint32_t bytesperblock;
88         } compression;
89         BASE_NS::Math::UVec4 swizzle;
90     };
91 
92     DeviceGLES(RenderContext& renderContext, DeviceCreateInfo const& createInfo);
93     ~DeviceGLES() override;
94 
95     // From IDevice
96     DeviceBackendType GetBackendType() const override;
97     const DevicePlatformData& GetPlatformData() const override;
98     AccelerationStructureBuildSizes GetAccelerationStructureBuildSizes(
99         const AccelerationStructureBuildGeometryInfo& geometry,
100         BASE_NS::array_view<const AccelerationStructureGeometryTrianglesInfo> triangles,
101         BASE_NS::array_view<const AccelerationStructureGeometryAabbsInfo> aabbs,
102         BASE_NS::array_view<const AccelerationStructureGeometryInstancesInfo> instances) const override;
103     FormatProperties GetFormatProperties(BASE_NS::Format format) const override;
104     ILowLevelDevice& GetLowLevelDevice() const override;
105     // NOTE: can be called from API
106     void WaitForIdle() override;
107 
108     PlatformGpuMemoryAllocator* GetPlatformGpuMemoryAllocator() override;
109 
110     // (re-)create swapchain
111     BASE_NS::unique_ptr<Swapchain> CreateDeviceSwapchain(const SwapchainCreateInfo& swapchainCreateInfo) override;
112     void DestroyDeviceSwapchain() override;
113 
114     bool IsActive() const;
115     void Activate() override;
116     void Deactivate() override;
117 
118     bool AllowThreadedProcessing() const override;
119 
120     GpuQueue GetValidGpuQueue(const GpuQueue& gpuQueue) const override;
121     uint32_t GetGpuQueueCount() const override;
122 
123     void InitializePipelineCache(BASE_NS::array_view<const uint8_t> initialData) override;
124     BASE_NS::vector<uint8_t> GetPipelineCache() const override;
125 
126     BASE_NS::unique_ptr<GpuBuffer> CreateGpuBuffer(const GpuBufferDesc& desc) override;
127     BASE_NS::unique_ptr<GpuBuffer> CreateGpuBuffer(const GpuAccelerationStructureDesc& desc) override;
128 
129     // Create gpu image resources
130     BASE_NS::unique_ptr<GpuImage> CreateGpuImage(const GpuImageDesc& desc) override;
131     BASE_NS::unique_ptr<GpuImage> CreateGpuImageView(
132         const GpuImageDesc& desc, const GpuImagePlatformData& platformData) override;
133     BASE_NS::unique_ptr<GpuImage> CreateGpuImageView(
134         const GpuImageDesc& desc, const BackendSpecificImageDesc& platformData) override;
135     BASE_NS::vector<BASE_NS::unique_ptr<GpuImage>> CreateGpuImageViews(const Swapchain& platformSwapchain) override;
136 
137     BASE_NS::unique_ptr<GpuSampler> CreateGpuSampler(const GpuSamplerDesc& desc) override;
138 
139     BASE_NS::unique_ptr<RenderFrameSync> CreateRenderFrameSync() override;
140 
141     BASE_NS::unique_ptr<RenderBackend> CreateRenderBackend(
142         GpuResourceManager& gpuResourceMgr, const CORE_NS::IParallelTaskQueue::Ptr& queue) override;
143 
144     BASE_NS::unique_ptr<ShaderModule> CreateShaderModule(const ShaderModuleCreateInfo& data) override;
145     BASE_NS::unique_ptr<ShaderModule> CreateComputeShaderModule(const ShaderModuleCreateInfo& data) override;
146     BASE_NS::unique_ptr<GpuShaderProgram> CreateGpuShaderProgram(const GpuShaderProgramCreateData& data) override;
147     BASE_NS::unique_ptr<GpuComputeProgram> CreateGpuComputeProgram(const GpuComputeProgramCreateData& data) override;
148 
149     BASE_NS::unique_ptr<NodeContextDescriptorSetManager> CreateNodeContextDescriptorSetManager() override;
150     BASE_NS::unique_ptr<NodeContextPoolManager> CreateNodeContextPoolManager(
151         class GpuResourceManager& gpuResourceMgr, const GpuQueue& gpuQueue) override;
152 
153     BASE_NS::unique_ptr<GraphicsPipelineStateObject> CreateGraphicsPipelineStateObject(
154         const GpuShaderProgram& gpuProgram, const GraphicsState& graphicsState, const PipelineLayout& pipelineLayout,
155         const VertexInputDeclarationView& vertexInputDeclaration,
156         const ShaderSpecializationConstantDataView& specializationConstants,
157         const BASE_NS::array_view<const DynamicStateEnum> dynamicStates, const RenderPassDesc& renderPassDesc,
158         const BASE_NS::array_view<const RenderPassSubpassDesc>& renderPassSubpassDescs, const uint32_t subpassIndex,
159         const LowLevelRenderPassData* renderPassData, const LowLevelPipelineLayoutData* pipelineLayoutData) override;
160 
161     BASE_NS::unique_ptr<ComputePipelineStateObject> CreateComputePipelineStateObject(
162         const GpuComputeProgram& gpuProgram, const PipelineLayout& pipelineLayout,
163         const ShaderSpecializationConstantDataView& specializationConstants,
164         const LowLevelPipelineLayoutData* pipelineLayoutData) override;
165 
166     BASE_NS::unique_ptr<GpuSemaphore> CreateGpuSemaphore() override;
167     BASE_NS::unique_ptr<GpuSemaphore> CreateGpuSemaphoreView(const uint64_t handle) override;
168 
169     void SetBackendConfig(const BackendConfig& config) override;
170 
171     // Internal apis, only usable by other parts of GLES backend.
172     bool HasExtension(BASE_NS::string_view extension) const;
173     void Activate(RenderHandle swapchain);
174 #if RENDER_HAS_GL_BACKEND
175     const WGLHelpers::WGLState& GetEglState();
176 #endif
177 #if RENDER_HAS_GLES_BACKEND
178     const EGLHelpers::EGLState& GetEglState();
179     bool IsDepthResolveSupported() const;
180 #endif
181 
182     uint32_t CacheProgram(
183         BASE_NS::string_view vertSource, BASE_NS::string_view fragSource, BASE_NS::string_view compSource);
184     void ReleaseProgram(uint32_t program);
185 
186     void UseProgram(uint32_t program);
187     void BindBuffer(uint32_t target, uint32_t buffer);
188     void BindBufferRange(uint32_t target, uint32_t binding, uint32_t buffer, uint64_t offset, uint64_t size);
189     void BindSampler(uint32_t textureUnit, uint32_t sampler);
190     void BindTexture(uint32_t textureUnit, uint32_t target, uint32_t texture); // target = GL_TEXTURE_2D et al.
191     void BindImageTexture(uint32_t unit, uint32_t texture, uint32_t level, bool layered, uint32_t layer,
192         uint32_t access, uint32_t format);
193     void BindFrameBuffer(uint32_t fbo);
194     void BindReadFrameBuffer(uint32_t fbo);
195     void BindWriteFrameBuffer(uint32_t fbo);
196     void BindVertexArray(uint32_t vao);
197 
198     void BindVertexBuffer(uint32_t slot, uint32_t buffer, intptr_t offset, intptr_t stride);
199     void VertexBindingDivisor(uint32_t slot, uint32_t divisor);
200     void BindElementBuffer(uint32_t buffer);
201 
202     uint32_t BoundReadFrameBuffer() const;
203     uint32_t BoundWriteFrameBuffer() const;
204 
205     uint32_t BoundProgram() const;
206     uint32_t BoundBuffer(uint32_t target) const;
207     uint32_t BoundBuffer(uint32_t target, uint32_t binding) const;
208     uint32_t BoundSampler(uint32_t textureUnit) const;
209     uint32_t BoundTexture(uint32_t textureUnit, uint32_t target) const;
210     uint32_t BoundVertexArray() const;
211 
212     // Creation functions for objects.
213     uint32_t CreateVertexArray();
214     // Deletion functions for objects.
215     void DeleteTexture(uint32_t texture);
216     void DeleteBuffer(uint32_t buffer);
217     void DeleteSampler(uint32_t sampler);
218     void DeleteVertexArray(uint32_t vao);
219     void DeleteFrameBuffer(uint32_t fbo);
220 
221     void SetActiveTextureUnit(uint32_t textureUnit); // hide this.
222     // swizzles for textures
223     void TexSwizzle(uint32_t image, uint32_t target, const BASE_NS::Math::UVec4& swizzle);
224     // texture upload / storage
225     void TexStorage2D(
226         uint32_t image, uint32_t target, uint32_t levels, uint32_t internalformat, const BASE_NS::Math::UVec2& extent);
227     void TexStorage3D(
228         uint32_t image, uint32_t target, uint32_t levels, uint32_t internalformat, const BASE_NS::Math::UVec3& extent);
229     void TexStorage2DMultisample(uint32_t image, uint32_t target, uint32_t samples, uint32_t internalformat,
230         const BASE_NS::Math::UVec2& extent, bool fixedsamplelocations);
231 
232     void TexSubImage2D(uint32_t image, uint32_t target, uint32_t level, const BASE_NS::Math::UVec2& offset,
233         const BASE_NS::Math::UVec2& extent, uint32_t format, uint32_t type, const void* pixels);
234     void TexSubImage3D(uint32_t image, uint32_t target, uint32_t level, const BASE_NS::Math::UVec3& offset,
235         const BASE_NS::Math::UVec3& extent, uint32_t format, uint32_t type, const void* pixels);
236     void CompressedTexSubImage2D(uint32_t image, uint32_t target, uint32_t level, const BASE_NS::Math::UVec2& offset,
237         const BASE_NS::Math::UVec2& extent, uint32_t format, uint32_t imageSize, const void* data);
238     void CompressedTexSubImage3D(uint32_t image, uint32_t target, uint32_t level, const BASE_NS::Math::UVec3& offset,
239         const BASE_NS::Math::UVec3& extent, uint32_t format, uint32_t imageSize, const void* data);
240 
241     const ImageFormat& GetGlImageFormat(BASE_NS::Format format) const;
242 
243     void SwapBuffers(const SwapchainGLES&);
244 
245 private:
246     enum BufferBindId : uint32_t {
247         UNIFORM_BUFFER_BIND = 0,
248         SHADER_STORAGE_BUFFER_BIND,
249 #ifdef HANDLE_UNSUPPORTED_ENUMS
250         ATOMIC_COUNTER_BUFFER_BIND,
251         TRANSFORM_FEEDBACK_BUFFER_BIND,
252 #endif
253         MAX_BUFFER_BIND_ID
254     };
255 
256     enum BufferTargetId : uint32_t {
257         PIXEL_UNPACK_BUFFER = 0,
258         PIXEL_PACK_BUFFER,
259         COPY_READ_BUFFER,
260         COPY_WRITE_BUFFER,
261         UNIFORM_BUFFER,
262         SHADER_STORAGE_BUFFER,
263         DISPATCH_INDIRECT_BUFFER,
264         DRAW_INDIRECT_BUFFER,
265 #ifdef HANDLE_UNSUPPORTED_ENUMS
266         ATOMIC_COUNTER_BUFFER,
267         QUERY_BUFFER,
268         TRANSFORM_FEEDBACK_BUFFER,
269         ARRAY_BUFFER,
270         ELEMENT_ARRAY_BUFFER, // stored in VAO state...
271         TEXTURE_BUFFER,
272 #endif
273         MAX_BUFFER_TARGET_ID
274     };
275 
276     enum TextureTargetId : uint32_t {
277         TEXTURE_2D = 0,
278         TEXTURE_CUBE_MAP = 1,
279 #if RENDER_HAS_GLES_BACKEND
280         TEXTURE_EXTERNAL_OES = 2,
281 #endif
282         TEXTURE_2D_MULTISAMPLE = 3,
283         TEXTURE_2D_ARRAY = 4,
284         TEXTURE_3D = 5,
285         MAX_TEXTURE_TARGET_ID
286     };
287 
288     static constexpr uint32_t READ_ONLY { 0x88B8 }; /* GL_READ_ONLY */
289     static constexpr uint32_t R32UI { 0x8236 };     /* GL_R32UI */
290     static constexpr uint32_t MAX_TEXTURE_UNITS { 16 };
291     static constexpr uint32_t MAX_SAMPLERS { 16 };
292     static constexpr uint32_t MAX_BOUND_IMAGE { 16 };
293     static constexpr uint32_t MAX_BINDING_VALUE { 16 };
294 
295     // Cleanup cache state when deleting objects.
296     void UnBindTexture(uint32_t texture);
297     void UnBindBuffer(uint32_t buffer);
298     void UnBindBufferFromVertexArray(uint32_t buffer);
299     void UnBindSampler(uint32_t sampler);
300     void UnBindVertexArray(uint32_t vao);
301     void UnBindFrameBuffer(uint32_t fbo);
302 
303     BASE_NS::vector<BASE_NS::string_view> extensions_;
304     BASE_NS::vector<ImageFormat> supportedFormats_;
305 
306     enum { VERTEX_CACHE = 0, FRAGMENT_CACHE = 1, COMPUTE_CACHE = 2, MAX_CACHES };
307     struct ShaderCache {
308         size_t hit { 0 };
309         size_t miss { 0 };
310         struct Entry {
311             uint32_t shader { 0 };
312             uint64_t hash { 0 }; // hash of generated GLSL
313             uint32_t refCount { 0 };
314         };
315         BASE_NS::vector<Entry> cache;
316     };
317     ShaderCache caches[MAX_CACHES];
318 
319     const ShaderCache::Entry& CacheShader(int type, BASE_NS::string_view source);
320     void ReleaseShader(uint32_t type, uint32_t shader);
321 
322     struct ProgramCache {
323         uint32_t program { 0 };
324         uint32_t vertShader { 0 };
325         uint32_t fragShader { 0 };
326         uint32_t compShader { 0 };
327         uint64_t hashVert { 0 };
328         uint64_t hashFrag { 0 };
329         uint64_t hashComp { 0 };
330         uint32_t refCount { 0 };
331     };
332     BASE_NS::vector<ProgramCache> programs_;
333     size_t pCacheHit_ { 0 };
334     size_t pCacheMiss_ { 0 };
335 
336 #if RENDER_HAS_GL_BACKEND
337 #if _WIN32
338     const DeviceBackendType backendType_ = DeviceBackendType::OPENGL;
339     WGLHelpers::WGLState eglState_;
340 #else
341 #error Core::DeviceBackendType::OPENGL not implemented for this platform yet.
342 #endif
343 #endif
344 #if RENDER_HAS_GLES_BACKEND
345     const DeviceBackendType backendType_ = DeviceBackendType::OPENGLES;
346     EGLHelpers::EGLState eglState_;
347     BackendConfigGLES backendConfig_ { {}, false };
348 #endif
349     mutable std::mutex activeMutex_;
350     uint32_t isActive_ { 0 };
351     bool isRenderbackendRunning_ { false };
352     BASE_NS::unique_ptr<LowLevelDeviceGLES> lowLevelDevice_;
353     // GL State cache..
354     // cache.
355     uint32_t activeTextureUnit_ = { 0 };
356     uint32_t boundSampler_[MAX_SAMPLERS] = { 0 };
357 
358     struct {
359         bool bound { false };
360         uint32_t texture { 0 };
361         uint32_t level { 0 };
362         bool layered { false };
363         uint32_t layer { 0 };
364         uint32_t access { READ_ONLY };
365         uint32_t format { R32UI };
366     } boundImage_[MAX_BOUND_IMAGE] = { {} };
367 
368     uint32_t boundTexture_[MAX_TEXTURE_UNITS][MAX_TEXTURE_TARGET_ID] = { { 0 } }; // [textureunit][target type]
369 
370     struct BufferCache {
371         bool cached { false };
372         uint32_t buffer { 0 };
373         uint64_t offset { 0 };
374         uint64_t size { 0 };
375     };
376     // Cache for GL_ATOMIC_COUNTER_BUFFER, GL_TRANSFORM_FEEDBACK_BUFFER, GL_UNIFORM_BUFFER, or GL_SHADER_STORAGE_BUFFER
377     // bindings.
378     BufferCache boundBuffers_[MAX_BUFFER_BIND_ID][MAX_BINDING_VALUE] = { {} };
379 
380     // bufferBound_ caches GL_PIXEL_UNPACK_BUFFER / GL_COPY_READ_BUFFER / GL_COPY_WRITE_BUFFER (and other generic
381     // bindings)
382     struct {
383         bool bound { false };
384         uint32_t buffer { 0 };
385     } bufferBound_[MAX_BUFFER_TARGET_ID];
386     uint32_t boundReadFbo_ { 0 };
387     uint32_t boundWriteFbo_ { 0 };
388     uint32_t boundVao_ { 0 };
389     uint32_t boundProgram_ { 0 };
390     struct VAOState {
391         uint32_t vao { 0 }; // GL name for object.
392         struct {
393             bool bound { false };
394             uint32_t buffer { 0 };
395         } elementBuffer;
396         struct {
397             bool bound { false };
398             uint32_t buffer { 0 };
399             intptr_t offset { 0 };
400             intptr_t stride { 0 };
401             uint32_t divisor { 0 };
402         } vertexBufferBinds[PipelineStateConstants::MAX_VERTEX_BUFFER_COUNT];
403     };
404     BASE_NS::vector<VAOState> vaoStates_;
405     size_t vaoStatesInUse_ = 0;
406 
407     // glid -> internal id
408     static BufferBindId IndexedTargetToTargetId(uint32_t target);
409     static uint32_t TargetToBinding(uint32_t target);
410     static BufferTargetId GenericTargetToTargetId(uint32_t target);
411     static TextureTargetId TextureTargetToTargetId(uint32_t target);
412 
413     // internal id -> glid
414     static uint32_t GenericTargetIdToTarget(BufferTargetId target);
415     static uint32_t IndexedTargetIdToTarget(BufferBindId target);
416     static uint32_t TextureTargetIdToTarget(TextureTargetId target);
417 };
418 
419 // Wrapper for low level device access
420 class LowLevelDeviceGLES final : public ILowLevelDeviceGLES {
421 public:
422     explicit LowLevelDeviceGLES(DeviceGLES& deviceGLES);
423     ~LowLevelDeviceGLES() = default;
424 
425     DeviceBackendType GetBackendType() const override;
426 
427 #if RENDER_HAS_EXPERIMENTAL
428     void Activate() override;
429     void Deactivate() override;
430     void SwapBuffers() override;
431 #endif
432 
433 private:
434     DeviceGLES& deviceGLES_;
435     GpuResourceManager& gpuResourceMgr_;
436 };
437 
438 #if (RENDER_HAS_GL_BACKEND)
439 BASE_NS::unique_ptr<Device> CreateDeviceGL(RenderContext& renderContext, DeviceCreateInfo const& createInfo);
440 #endif
441 #if (RENDER_HAS_GLES_BACKEND)
442 BASE_NS::unique_ptr<Device> CreateDeviceGLES(RenderContext& renderContext, DeviceCreateInfo const& createInfo);
443 #endif
444 RENDER_END_NAMESPACE()
445 
446 #endif // GLES_DEVICE_GLES_H
447