• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 <map>
22 #include <mutex>
23 
24 #include <base/containers/string_view.h>
25 #include <base/containers/unique_ptr.h>
26 #include <base/containers/vector.h>
27 #include <base/math/vector.h>
28 #include <base/namespace.h>
29 #include <render/device/pipeline_state_desc.h>
30 #include <render/gles/intf_device_gles.h>
31 #include <render/namespace.h>
32 #include <render/resource_handle.h>
33 
34 #include "device/device.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 GpuAccelerationStructure;
46 class GpuBuffer;
47 class GpuComputeProgram;
48 class GpuImage;
49 class GpuResourceManager;
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     void 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 
128     // Create gpu image resources
129     BASE_NS::unique_ptr<GpuImage> CreateGpuImage(const GpuImageDesc& desc) override;
130     BASE_NS::unique_ptr<GpuImage> CreateGpuImageView(
131         const GpuImageDesc& desc, const GpuImagePlatformData& platformData) override;
132     BASE_NS::unique_ptr<GpuImage> CreateGpuImageView(
133         const GpuImageDesc& desc, const BackendSpecificImageDesc& platformData) override;
134     BASE_NS::vector<BASE_NS::unique_ptr<GpuImage>> CreateGpuImageViews(const Swapchain& platformSwapchain) override;
135 
136     BASE_NS::unique_ptr<GpuSampler> CreateGpuSampler(const GpuSamplerDesc& desc) override;
137 
138     BASE_NS::unique_ptr<GpuAccelerationStructure> CreateGpuAccelerationStructure(
139         const GpuAccelerationStructureDesc& desc) override;
140 
141     BASE_NS::unique_ptr<RenderFrameSync> CreateRenderFrameSync() override;
142 
143     BASE_NS::unique_ptr<RenderBackend> CreateRenderBackend(
144         GpuResourceManager& gpuResourceMgr, const CORE_NS::IParallelTaskQueue::Ptr& queue) override;
145 
146     BASE_NS::unique_ptr<ShaderModule> CreateShaderModule(const ShaderModuleCreateInfo& data) override;
147     BASE_NS::unique_ptr<ShaderModule> CreateComputeShaderModule(const ShaderModuleCreateInfo& data) override;
148     BASE_NS::unique_ptr<GpuShaderProgram> CreateGpuShaderProgram(const GpuShaderProgramCreateData& data) override;
149     BASE_NS::unique_ptr<GpuComputeProgram> CreateGpuComputeProgram(const GpuComputeProgramCreateData& data) override;
150 
151     BASE_NS::unique_ptr<NodeContextDescriptorSetManager> CreateNodeContextDescriptorSetManager() override;
152     BASE_NS::unique_ptr<NodeContextPoolManager> CreateNodeContextPoolManager(
153         class GpuResourceManager& gpuResourceMgr, const GpuQueue& gpuQueue) override;
154 
155     BASE_NS::unique_ptr<GraphicsPipelineStateObject> CreateGraphicsPipelineStateObject(
156         const GpuShaderProgram& gpuProgram, const GraphicsState& graphicsState, const PipelineLayout& pipelineLayout,
157         const VertexInputDeclarationView& vertexInputDeclaration,
158         const ShaderSpecializationConstantDataView& specializationConstants, const DynamicStateFlags dynamicStateFlags,
159         const RenderPassDesc& renderPassDesc,
160         const BASE_NS::array_view<const RenderPassSubpassDesc>& renderPassSubpassDescs, const uint32_t subpassIndex,
161         const LowLevelRenderPassData* renderPassData, const LowLevelPipelineLayoutData* pipelineLayoutData) override;
162 
163     BASE_NS::unique_ptr<ComputePipelineStateObject> CreateComputePipelineStateObject(
164         const GpuComputeProgram& gpuProgram, const PipelineLayout& pipelineLayout,
165         const ShaderSpecializationConstantDataView& specializationConstants,
166         const LowLevelPipelineLayoutData* pipelineLayoutData) override;
167 
168     // Internal apis, only usable by other parts of GLES backend.
169     bool HasExtension(BASE_NS::string_view extension) const;
170 #if RENDER_HAS_GL_BACKEND
171     const WGLHelpers::WGLState& GetEglState();
172 #endif
173 #if RENDER_HAS_GLES_BACKEND
174     const EGLHelpers::EGLState& GetEglState();
175 #endif
176 
177     uint32_t CacheProgram(
178         BASE_NS::string_view vertSource, BASE_NS::string_view fragSource, BASE_NS::string_view compSource);
179     void ReleaseProgram(uint32_t program);
180     SwapchainGLES* GetSwapchain();
181 
182     void UseProgram(uint32_t program);
183     void BindBuffer(uint32_t target, uint32_t buffer);
184     void BindBufferRange(uint32_t target, uint32_t binding, uint32_t buffer, uint64_t offset, uint64_t size);
185     void BindSampler(uint32_t textureUnit, uint32_t sampler);
186     void BindTexture(uint32_t textureUnit, uint32_t target, uint32_t texture); // target = GL_TEXTURE_2D et al.
187     void BindImageTexture(uint32_t unit, uint32_t texture, uint32_t level, bool layered, uint32_t layer,
188         uint32_t access, uint32_t format);
189     void BindFrameBuffer(uint32_t fbo);
190     void BindReadFrameBuffer(uint32_t fbo);
191     void BindWriteFrameBuffer(uint32_t fbo);
192     void BindVertexArray(uint32_t vao);
193 
194     void BindVertexBuffer(uint32_t slot, uint32_t buffer, intptr_t offset, intptr_t stride);
195     void VertexBindingDivisor(uint32_t slot, uint32_t divisor);
196     void BindElementBuffer(uint32_t buffer);
197 
198     uint32_t BoundReadFrameBuffer() const;
199     uint32_t BoundWriteFrameBuffer() const;
200 
201     uint32_t BoundProgram() const;
202     uint32_t BoundBuffer(uint32_t target) const;
203     uint32_t BoundBuffer(uint32_t target, uint32_t binding) const;
204     uint32_t BoundSampler(uint32_t textureUnit) const;
205     uint32_t BoundTexture(uint32_t textureUnit, uint32_t target) const;
206     uint32_t BoundVertexArray() const;
207 
208     // Creation functions for objects.
209     uint32_t CreateVertexArray();
210     // Deletion functions for objects.
211     void DeleteTexture(uint32_t texture);
212     void DeleteBuffer(uint32_t buffer);
213     void DeleteSampler(uint32_t sampler);
214     void DeleteVertexArray(uint32_t vao);
215     void DeleteFrameBuffer(uint32_t fbo);
216 
217     void SetActiveTextureUnit(uint32_t textureUnit); // hide this.
218     // swizzles for textures
219     void TexSwizzle(uint32_t image, uint32_t target, const BASE_NS::Math::UVec4& swizzle);
220     // texture upload / storage
221     void TexStorage2D(
222         uint32_t image, uint32_t target, uint32_t levels, uint32_t internalformat, const BASE_NS::Math::UVec2& extent);
223     void TexStorage3D(
224         uint32_t image, uint32_t target, uint32_t levels, uint32_t internalformat, const BASE_NS::Math::UVec3& extent);
225     void TexStorage2DMultisample(uint32_t image, uint32_t target, uint32_t samples, uint32_t internalformat,
226         const BASE_NS::Math::UVec2& extent, bool fixedsamplelocations);
227 
228     void TexSubImage2D(uint32_t image, uint32_t target, uint32_t level, const BASE_NS::Math::UVec2& offset,
229         const BASE_NS::Math::UVec2& extent, uint32_t format, uint32_t type, const void* pixels);
230     void TexSubImage3D(uint32_t image, uint32_t target, uint32_t level, const BASE_NS::Math::UVec3& offset,
231         const BASE_NS::Math::UVec3& extent, uint32_t format, uint32_t type, const void* pixels);
232     void CompressedTexSubImage2D(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 imageSize, const void* data);
234     void CompressedTexSubImage3D(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 imageSize, const void* data);
236 
237     const ImageFormat& GetGlImageFormat(BASE_NS::Format format) const;
238 
239 private:
240     enum BufferBindId : uint32_t {
241         UNIFORM_BUFFER_BIND = 0,
242         SHADER_STORAGE_BUFFER_BIND,
243 #ifdef HANDLE_UNSUPPORTED_ENUMS
244         ATOMIC_COUNTER_BUFFER_BIND,
245         TRANSFORM_FEEDBACK_BUFFER_BIND,
246 #endif
247         MAX_BUFFER_BIND_ID
248     };
249 
250     enum BufferTargetId : uint32_t {
251         PIXEL_UNPACK_BUFFER = 0,
252         PIXEL_PACK_BUFFER,
253         COPY_READ_BUFFER,
254         COPY_WRITE_BUFFER,
255         UNIFORM_BUFFER,
256         SHADER_STORAGE_BUFFER,
257         DISPATCH_INDIRECT_BUFFER,
258         DRAW_INDIRECT_BUFFER,
259 #ifdef HANDLE_UNSUPPORTED_ENUMS
260         ATOMIC_COUNTER_BUFFER,
261         QUERY_BUFFER,
262         TRANSFORM_FEEDBACK_BUFFER,
263         ARRAY_BUFFER,
264         ELEMENT_ARRAY_BUFFER, // stored in VAO state...
265         TEXTURE_BUFFER,
266 #endif
267         MAX_BUFFER_TARGET_ID
268     };
269 
270     enum TextureTargetId : uint32_t {
271         TEXTURE_2D = 0,
272         TEXTURE_CUBE_MAP = 1,
273 #if RENDER_HAS_GLES_BACKEND
274         TEXTURE_EXTERNAL_OES = 2,
275 #endif
276         TEXTURE_2D_MULTISAMPLE = 3,
277         TEXTURE_2D_ARRAY = 4,
278         MAX_TEXTURE_TARGET_ID
279     };
280 
281     static constexpr uint32_t READ_ONLY { 0x88B8 }; /* GL_READ_ONLY */
282     static constexpr uint32_t R32UI { 0x8236 };     /* GL_R32UI */
283     static constexpr uint32_t MAX_TEXTURE_UNITS { 16 };
284     static constexpr uint32_t MAX_SAMPLERS { 16 };
285     static constexpr uint32_t MAX_BOUND_IMAGE { 16 };
286     static constexpr uint32_t MAX_BINDING_VALUE { 16 };
287 
288     // Cleanup cache state when deleting objects.
289     void UnBindTexture(uint32_t texture);
290     void UnBindBuffer(uint32_t buffer);
291     void UnBindBufferFromVertexArray(uint32_t buffer);
292     void UnBindSampler(uint32_t sampler);
293     void UnBindVertexArray(uint32_t vao);
294     void UnBindFrameBuffer(uint32_t fbo);
295 
296     std::map<BASE_NS::string, bool> extensions_;
297     BASE_NS::vector<ImageFormat> supportedFormats_;
298 
299     enum { VERTEX_CACHE = 0, FRAGMENT_CACHE = 1, COMPUTE_CACHE = 2, MAX_CACHES };
300     struct ShaderCache {
301         size_t hit { 0 };
302         size_t miss { 0 };
303         struct Entry {
304             uint32_t shader { 0 };
305             uint64_t hash { 0 }; // hash of generated GLSL
306             uint32_t refCount { 0 };
307         };
308         BASE_NS::vector<Entry> cache;
309     };
310     ShaderCache caches[MAX_CACHES];
311 
312     const ShaderCache::Entry& CacheShader(int type, BASE_NS::string_view source);
313     void ReleaseShader(uint32_t type, uint32_t shader);
314 
315     struct ProgramCache {
316         uint32_t program { 0 };
317         uint32_t vertShader { 0 };
318         uint32_t fragShader { 0 };
319         uint32_t compShader { 0 };
320         uint64_t hashVert { 0 };
321         uint64_t hashFrag { 0 };
322         uint64_t hashComp { 0 };
323         uint32_t refCount { 0 };
324     };
325     BASE_NS::vector<ProgramCache> programs_;
326     size_t pCacheHit_ { 0 };
327     size_t pCacheMiss_ { 0 };
328 
329 #if RENDER_HAS_GL_BACKEND
330 #if _WIN32
331     const DeviceBackendType backendType_ = DeviceBackendType::OPENGL;
332     WGLHelpers::WGLState eglState_;
333 #else
334 #error Core::DeviceBackendType::OPENGL not implemented for this platform yet.
335 #endif
336 #endif
337 #if RENDER_HAS_GLES_BACKEND
338     const DeviceBackendType backendType_ = DeviceBackendType::OPENGLES;
339     EGLHelpers::EGLState eglState_;
340 #endif
341     mutable std::mutex activeMutex_;
342     uint32_t isActive_ { 0 };
343     bool isRenderbackendRunning_ { false };
344     BASE_NS::unique_ptr<LowLevelDeviceGLES> lowLevelDevice_;
345     // GL State cache..
346     // cache.
347     uint32_t activeTextureUnit_ = { 0 };
348     uint32_t boundSampler_[MAX_SAMPLERS] = { 0 };
349 
350     struct {
351         bool bound { false };
352         uint32_t texture { 0 };
353         uint32_t level { 0 };
354         bool layered { false };
355         uint32_t layer { 0 };
356         uint32_t access { READ_ONLY };
357         uint32_t format { R32UI };
358     } boundImage_[MAX_BOUND_IMAGE] = { {} };
359 
360     uint32_t boundTexture_[MAX_TEXTURE_UNITS][MAX_TEXTURE_TARGET_ID] = { { 0 } }; // [textureunit][target type]
361 
362     struct BufferCache {
363         bool cached { false };
364         uint32_t buffer { 0 };
365         uint64_t offset { 0 };
366         uint64_t size { 0 };
367     };
368     // Cache for GL_ATOMIC_COUNTER_BUFFER, GL_TRANSFORM_FEEDBACK_BUFFER, GL_UNIFORM_BUFFER, or GL_SHADER_STORAGE_BUFFER
369     // bindings.
370     BufferCache boundBuffers_[MAX_BUFFER_BIND_ID][MAX_BINDING_VALUE] = { {} };
371 
372     // bufferBound_ caches GL_PIXEL_UNPACK_BUFFER / GL_COPY_READ_BUFFER / GL_COPY_WRITE_BUFFER (and other generic
373     // bindings)
374     struct {
375         bool bound { false };
376         uint32_t buffer { 0 };
377     } bufferBound_[MAX_BUFFER_TARGET_ID];
378     uint32_t boundReadFbo_ { 0 };
379     uint32_t boundWriteFbo_ { 0 };
380     uint32_t boundVao_ { 0 };
381     uint32_t boundProgram_ { 0 };
382     struct VAOState {
383         uint32_t vao { 0 }; // GL name for object.
384         struct {
385             bool bound { false };
386             uint32_t buffer { 0 };
387         } elementBuffer;
388         struct {
389             bool bound { false };
390             uint32_t buffer { 0 };
391             intptr_t offset { 0 };
392             intptr_t stride { 0 };
393             uint32_t divisor { 0 };
394         } vertexBufferBinds[PipelineStateConstants::MAX_VERTEX_BUFFER_COUNT];
395     };
396     BASE_NS::vector<VAOState> vaoStates_;
397     size_t vaoStatesInUse_ = 0;
398 
399     // glid -> internal id
400     static BufferBindId IndexedTargetToTargetId(uint32_t target);
401     static uint32_t TargetToBinding(uint32_t target);
402     static BufferTargetId GenericTargetToTargetId(uint32_t target);
403     static TextureTargetId TextureTargetToTargetId(uint32_t target);
404 
405     // internal id -> glid
406     static uint32_t GenericTargetIdToTarget(BufferTargetId target);
407     static uint32_t IndexedTargetIdToTarget(BufferBindId target);
408     static uint32_t TextureTargetIdToTarget(TextureTargetId target);
409 };
410 
411 // Wrapper for low level device access
412 class LowLevelDeviceGLES final : public ILowLevelDeviceGLES {
413 public:
414     explicit LowLevelDeviceGLES(DeviceGLES& deviceGLES);
415     ~LowLevelDeviceGLES() = default;
416 
417     DeviceBackendType GetBackendType() const override;
418 
419 private:
420     DeviceGLES& deviceGLES_;
421     GpuResourceManager& gpuResourceMgr_;
422 };
423 
424 #if (RENDER_HAS_GL_BACKEND)
425 BASE_NS::unique_ptr<Device> CreateDeviceGL(RenderContext& renderContext, DeviceCreateInfo const& createInfo);
426 #endif
427 #if (RENDER_HAS_GLES_BACKEND)
428 BASE_NS::unique_ptr<Device> CreateDeviceGLES(RenderContext& renderContext, DeviceCreateInfo const& createInfo);
429 #endif
430 RENDER_END_NAMESPACE()
431 
432 #endif // GLES_DEVICE_GLES_H
433