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