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