Compare commits

...
Author SHA1 Message Date
BZLZHH 8f950fc345 [Chore] (Global): Disable debug. Set log target to all. 2025-07-11 09:17:57 +08:00
BZLZHH 83cfacf94b [Fix] (MG_State/Buffer): Prevent crashing when buffer obj is not created but is going to be deleted. 2025-07-10 23:08:38 +08:00
BZLZHH dae5827666 [Fix] (MG_Util/GLSL): Enhance BindInputLayoutLocationsForGLSL. 2025-07-10 23:07:44 +08:00
BZLZHH b119c45c16 [Feat] (Diligent/Drawing): Convert Uint8 IBO into Uint16. 2025-07-10 19:45:24 +08:00
swung0x48 a59fe679a7 Merge branch 'Feat/Diligent' of https://github.com/MobileGL-Dev/MobileGL into feat/Diligent 2025-07-10 18:04:41 +08:00
swung0x48 82a4be37f2 [Fix] (MG_State/Program): fixing discrapencies between builtins of Vulkan and OpenGL GLSL (gl_VertexID/gl_VertexIndex) 2025-07-10 18:04:19 +08:00
BZLZHH f56453093f [Improvement] (Diligent/PSO): Add UniformStageCache. 2025-07-10 17:09:53 +08:00
BZLZHH 59e0291f9e [Improvement] (HeaderSystem): Optimize header system, highly improving performance. 2025-07-10 14:01:09 +08:00
BZLZHH 833679e58a [Chore] (gitignore): Ignore Visual Studio directory and output directory. 2025-07-10 11:41:33 +08:00
BZLZHH f04207905f [Chore] (DEBUG): Enable debug. 2025-07-09 18:17:10 +08:00
swung0x48 8c98afb1ac [Fix] (MG_State/Buffer): 1. Don't check on GetBufferObject(), do it on creation 2. Don't modify g_BufferMap on querying 2025-07-08 17:53:21 +08:00
swung0x48 8c52cd34ed [Fix] (MG_State/Clear): set render targets before clear 2025-07-08 16:17:47 +08:00
swung0x48 fbb1fc1fdb [Misc] (MG_State/Buffer): reserve buffer size rounding up to next power of 2 to make resize complexity logarithmic 2025-07-08 15:44:11 +08:00
swung0x48 c43ae7ed2c [Misc] (Diligent/Present): hard code disable vsync for now 2025-07-08 15:42:18 +08:00
swung0x48 ad626025d5 [Fix] (Diligent/Init): request NativeMultiDraw feature 2025-07-08 15:41:10 +08:00
swung0x48 9db24e6593 [Optimization] (Diligent/Framebuffer): explicitly unbind framebuffer on texture copy (BlitFramebuffer) 2025-07-08 14:32:25 +08:00
swung0x48 e3765f1f50 [Optimization] (MG_Constant): use vector instead of unordered_set to improve performance 2025-07-08 12:39:39 +08:00
swung0x48 532ca5ced5 [Fix] (MG_State/Texture, MG_State/Framebuffer): add stub for glCopyTexSubImage2D, glDrawBuffer, glDrawBuffers and glReadBuffer 2025-07-08 11:05:59 +08:00
swung0x48 20d02b75e1 [Fix] (MG_State/Texture): re-enable multi-miplevels 2025-07-07 10:39:00 +08:00
swung0x48 992ea967a7 [Fix] (MG_State/Texture): correctly maintain mag filter compare mode 2025-07-07 10:05:19 +08:00
swung0x48 9e3a5aefad [Optimize] (Diligent/RenderPass): remove renderpass usage 2025-07-06 10:21:15 +08:00
BZLZHH bf0c29b384 [Fix] (MG_Util/Program): Completely fix uniform conflicting. 2025-07-05 12:25:22 +08:00
BZLZHH 164c2f25d4 [Fix] (MG_Util/Program): Avoid uniform variables conflicting. 2025-07-05 11:56:15 +08:00
BZLZHH 4cf85c4f2a [Fix] (MG_State/Program): Map IO binding in FinalizeProgramPipeline. 2025-07-05 10:28:39 +08:00
swung0x48 bcaf0e6e32 Revert "[Fix] (MG_Util/GLSLTool): actually linking & mapping IO?"
This reverts commit 92cd0f3a82.
2025-07-04 20:11:33 +08:00
swung0x48 92cd0f3a82 [Fix] (MG_Util/GLSLTool): actually linking & mapping IO? 2025-07-02 14:35:41 +08:00
swung0x48 067d517527 [Fix] (MG_Util/GLSLTool): get rid of unnecessary whitespace removal 2025-06-30 15:32:59 +08:00
swung0x48 a6bcded3e4 [Fix] (Diligent/Drawing): set g_TriangleFanIndexBuffer to null after release 2025-06-30 13:48:24 +08:00
swung0x48 79e5eb6a74 [Fix] (MG_State/Buffer): ignore 0-sized reallocation 2025-06-30 13:47:07 +08:00
swung0x48 1078a33147 [Fix] (MG_Util/GLSLTool): set preamble to fix compilation error with vulkan target 2025-06-30 13:02:09 +08:00
swung0x48 3fb314fc44 [Fix] (MG_Util/GLSLTool): specify vulkan semantics to convert gl_VertexID/gl_InstanceID 2025-06-30 12:29:45 +08:00
BZLZHH e1fd5678ec [Fix] (Diligent/Shader): Try to bind varying in glsl str. 2025-06-29 11:42:38 +08:00
swung0x48 8a0d00f94b [Optimize] (MG_State/Buffer): vector to replace umap (does that optimize anything?) 2025-06-29 01:02:00 +08:00
swung0x48 0207ee85b7 [Optimize] (MG_Util/Debug): avoid runtime cost of unneeded log function (forced at compile time) 2025-06-27 22:29:24 +08:00
swung0x48 a5a661261d [Feat] (Diligent/EGL_Init, MG_State/Getter): separates engine init and swapchain creation 2025-06-27 13:47:43 +08:00
swung0x48 d056acf0af [Feat] (Diligent/PSO, MG_State/Buffer): implement GL_TRIANGLE_FAN emulation, fixing sky 2025-06-27 10:14:05 +08:00
swung0x48 229b5f292e [Fix] (MG_State/Texture): revert GetUnpackParam_ to private 2025-06-26 16:03:34 +08:00
swung0x48 3e71f83d61 [Fix] (MG_State/Texture): implement GL_UNPACK_SKIP_ROWS and GL_UNPACK_SKIP_PIXELS, fixing non-unicode fonts 2025-06-26 13:58:07 +08:00
swung0x48 fa6ace0955 [Misc]: minor fixes 2025-06-25 23:49:43 +08:00
swung0x48 1e6f91809e [Fix] (MG_State/Texture): deal with GL_UNPACK_ROW_LENGTH 2025-06-25 23:48:24 +08:00
swung0x48 afcc892b32 [Misc] (MG_GL/Getter): return real GL_MAX_VERTEX_ATTRIBS value 2025-06-25 17:02:34 +08:00
swung0x48 1c0a1fcbcb [Misc] (MG_State/Drawing): minor optimizations 2025-06-25 16:59:50 +08:00
swung0x48 bf8aaaa9c1 [Fix] (MG_State/VertexArray): use array to save attribs to maintain order and optimize performance 2025-06-25 16:22:16 +08:00
swung0x48 0359a4e97f [Fix] (MG_State/Texture): get rid of 0.25 max lod clamp 2025-06-25 11:58:51 +08:00
swung0x48 a18360c931 [Fix] (MG_State/PSO, GLSLTool): revert to flip y in shader 2025-06-24 17:36:45 +08:00
swung0x48 0c031d3e0b [Fix] (MG/GLSLTool): Finally fixing blur shader!
- use glslang mapIO() function to correctly link shader in/out varyings
- no need to flip y (already using VK_KHR_maintenance1 to specify negative viewport height)
- use pointers to avoid unnecessary copying
2025-06-24 16:33:16 +08:00
swung0x48 20a945c6f0 [Misc] (MG_State/PSO): temporarily disable culling, deal with cw/ccw later 2025-06-24 16:27:20 +08:00
swung0x48 433a5ac39d [Fix] (MG_State/GL_Texture): no need to clamp max lod min value 2025-06-24 16:26:09 +08:00
swung0x48 b444b7de88 [Fix] (MG_State/GL_Texture): do not automatically generate mipmaps 2025-06-24 09:02:50 +08:00
swung0x48 94dfdb6905 [Fix] (MG_Util/Program/GLSLTool): Really really hacky way to fix blur shader 2025-06-23 23:24:39 +08:00
swung0x48 2f1b06d0f9 [Fix] (MG/Framebuffer): get rid of suspicious GL_FRAMEBUFFER handling 2025-06-23 10:51:24 +08:00
swung0x48 14b1d5a2d1 [Fix] (MG/Constants): put log level in order 2025-06-23 09:37:32 +08:00
swung0x48 7c3912b9ae [Feat] (MG_State/Texture): implement GL_TEXTURE_COMPARE_MODE 2025-06-23 09:32:25 +08:00
swung0x48 fa657fbf0b [Misc] (Diligent/Texture): Log unhandled texture state 2025-06-22 22:00:17 +08:00
swung0x48 6e9f990eed [Fix] (Diligent/PSO,Program): get rid of phantom program 0 2025-06-22 21:59:20 +08:00
swung0x48 a8ae34b3bd [Improvement] (Getter): better glGetString with GPU name 2025-06-22 19:57:41 +08:00
swung0x48 e959126ac0 [Fix] (MG_State/Texture): properly disable mip filter when instructed 2025-06-22 19:56:15 +08:00
swung0x48 7e1906da57 [Fix] (MG_State/Texture): add same handling logic to glTexParameterf 2025-06-22 17:40:38 +08:00
swung0x48 9075177533 [Fix] (MG_State/Texture): Handle missing texture states 2025-06-22 13:08:50 +08:00
swung0x48 e73db426eb [Fix] (DebugTool.cpp): Fix uniform value debug output 2025-06-22 10:20:15 +08:00
BZLZHH 150bfa15a6 [Fix] (DiligentEngine): Increase the size of dynamic heap buffer. 2025-06-21 22:07:14 +08:00
BZLZHH cab375917b [Fix] (Diligent/PSO): Disable FrontCounterClockwise currently. 2025-06-21 21:44:43 +08:00
BZLZHH 6ac9beaa61 [Fix] (Diligent/Shader): Flip vertex y for vertex shaders. 2025-06-21 21:44:22 +08:00
BZLZHH a1bdaed2f6 [Chore] (DiligentEngine): Rename the renderer with Diligent Engine. 2025-06-21 21:43:32 +08:00
BZLZHH ee29a397da [Fix] (Diligent/PSO): Use GLSL For Vulkan mode somewhere. 2025-06-21 19:35:16 +08:00
BZLZHH cbf63dd2b6 [Fix] (MG_Util/Program): Allow GLSL For Vulkan to be converted into spirv. 2025-06-21 19:34:13 +08:00
BZLZHH 6d73806d1a [Fix] (Diligent/PSO): Use SPIRV-Cross to get the uniform offset. 2025-06-21 18:35:06 +08:00
BZLZHH f6c416bdf1 [Fix] (Diligent/Drawing): Prevent shader missing when shader has been deleted. 2025-06-21 17:04:32 +08:00
BZLZHH 99dd2f5dec [Fix] (Diligent/Buffer): Fix flags absence of buffer objects in Diligent. 2025-06-21 13:23:40 +08:00
BZLZHH d3b94dd1c6 [Fix] (Diligent/Drawing): Set IBO in glMultiDrawElementsBaseVertex. 2025-06-21 12:24:02 +08:00
BZLZHH edd1ad1a80 [Fix] (MG_State/Buffer): Do not consider GL_DYNAMIC_COPY and GL_STREAM_DRAW as dynamic buffer. 2025-06-21 11:30:47 +08:00
BZLZHH ae5c37b7e4 [Fix] (Diligent/Drawing): Fix vertex in glMultiDrawElements, 2025-06-21 10:41:19 +08:00
BZLZHH 7c3b4e52c3 [Feat] (Diligent/Drawing): Reimplement glMultiDrawElements through indirect drawing. 2025-06-21 09:48:08 +08:00
BZLZHH 61ae5e2e34 [Feat] (Diligent/Drawing): Implement glMultiDrawElements. 2025-06-21 04:11:40 +08:00
BZLZHH 6992c541af [Fix] (Diligent/Framebuffer): Correct GL_FRAMEBUFFER target handling. 2025-06-21 02:02:51 +08:00
BZLZHH 5d6bf42397 [Fix] (MG_State/Framebuffer): Correct GL_FRAMEBUFFER target handling and resource management. 2025-06-21 02:02:26 +08:00
BZLZHH bc61669dad [Improvement] (All): Remove redundant code. 2025-06-20 23:44:20 +08:00
BZLZHH 537ec9e2b0 [Fix] (Diligent/PSO): Try hashing bound texture ids for PSO. 2025-06-20 23:42:38 +08:00
BZLZHH 4ae9c00c06 Reapply "[Fix] (EGL_impl.cpp): make swapchain rotation right"
This reverts commit 832fc56a1b.
2025-06-20 21:55:53 +08:00
BZLZHH 3583e24bd8 Merge remote-tracking branch 'origin/dev-es' into Feat/Diligent 2025-06-20 17:56:01 +08:00
BZLZHH 832fc56a1b Revert "[Fix] (EGL_impl.cpp): make swapchain rotation right"
This reverts commit db93ddd280.

# Conflicts:
#	MG/MG_GL/Implementations/EGL/Diligent/EGL_impl.cpp
2025-06-20 16:50:29 +08:00
BZLZHH e77b56c9ad [Fix] (Diligent/PSO): Avoid crashing when MG_DEFAULT_UBO does not exist. 2025-06-20 16:41:13 +08:00
BZLZHH ac4cb2217e [Fix] (Diligent/Framebuffer): Do not begin renderpass in glBindFramebuffer. 2025-06-20 16:40:33 +08:00
BZLZHH cc2177e36c [Fix] (Diligent/Common): Handle renderpass in glClear. 2025-06-20 16:39:43 +08:00
BZLZHH ac6827fdd8 [Fix] (Diligent/Texture): Set sampler for texture. 2025-06-20 15:42:31 +08:00
BZLZHH 3c30d3aba9 Merge branch 'dev-es' into Feat/Diligent
# Conflicts:
#	MG/Constants.h
#	MG/Global.h
2025-06-20 13:25:44 +08:00
BZLZHH e4c77d1432 [Improvement] (MG_State/Program): Optimize the logic for DeleteShader. 2025-06-20 12:50:42 +08:00
BZLZHH e8ca8161c8 [Fix] (Diligent/Shader): Do not delete the Diligent shader obj when glDeleteShader is called. 2025-06-20 12:49:09 +08:00
swung0x48 a65ae7202e [Fix] (EGL_impl.cpp): probably fixed PSO hashing 2025-06-19 16:53:58 +08:00
swung0x48 09d13579fc [Fix]: PSO caching broken? Just re-generate on mismatch (TODO: fix this later) 2025-06-19 15:55:17 +08:00
swung0x48 3d2596f701 [Optimization] (EGL_impl.cpp): don't copy the whole unordered_map 2025-06-18 16:21:07 +08:00
swung0x48 6bc28c2ae9 [Fix] (EGL_impl.cpp): properly implement colorMask 2025-06-18 16:16:51 +08:00
swung0x48 2cd5edd08b [Fix] (EGL_impl.cpp): fix PSO hashing bugs 2025-06-18 13:05:06 +08:00
swung0x48 58a46c6106 [Fix] (EGL_impl.cpp): use RGBA8_UNORM as ColorBufferFormat, avoiding auto sRGB color correction 2025-06-18 10:36:08 +08:00
swung0x48 db93ddd280 [Fix] (EGL_impl.cpp): make swapchain rotation right 2025-06-18 10:18:01 +08:00
BZLZHH 6a1b1a5ed9 [Fix] (Diligent/PSO): Miscellaneous fix. 2025-06-15 11:52:34 +08:00
BZLZHH df95930481 [Fix] (DiligentEngine): Increase the size of dynamic heap buffer. 2025-06-15 10:33:17 +08:00
BZLZHH 0c2449dc5e [Fix] (Diligent/Buffer): Recreate buffer object when the size changes. 2025-06-15 10:32:38 +08:00
BZLZHH 8fcf58a732 [Fix] (Diligent/PSO): Correct std140 alignment in uniform offset recording. 2025-06-15 09:37:21 +08:00
BZLZHH 937cab736b [Feat] (Diligent/Drawing): Handle uint8 in MultiDrawElementsBaseVertex. 2025-06-15 08:13:22 +08:00
BZLZHH fa7bb59a82 [Feat] (Diligent/Drawing): Implement (Multi)DrawElementsBaseVertex. 2025-06-10 02:15:56 +08:00
BZLZHH a0016861e8 [Fix] (Diligent/PSO): Avoid crashing when uniform data is invalid. 2025-06-10 01:55:04 +08:00
BZLZHH 964f483fd5 [Fix] (Diligent/Buffer): Make all types of buffer mappable. 2025-06-10 01:54:19 +08:00
BZLZHH c5ea0a7bf1 [Fix] (BufferState): Better judgement for obj.isDynamic. 2025-06-10 01:53:42 +08:00
BZLZHH aad270bcd0 [Fix] (Diligent/PSO): Do not use immutable samplers. 2025-06-10 01:00:20 +08:00
BZLZHH 994e0a6675 [Misc] (Debug): Improve some logging. 2025-06-09 19:12:25 +08:00
BZLZHH 836c169100 [Fix] (Diligent/Shader): Rename glsl builtins for Vulkan. 2025-06-09 19:10:01 +08:00
BZLZHH 2fb0690804 [Fix] (Diligent/PSO): Try to bind input layout locations for GLSL. 2025-06-09 13:38:16 +08:00
BZLZHH 30b7f4d69d [Fix] (Diligent/Texture): Make multi-level textures correct. 2025-06-09 01:54:11 +08:00
BZLZHH 44e787c56a [Fix] (Diligent/PSO): Get real stage for uniform sampler. 2025-06-09 00:26:41 +08:00
BZLZHH 0c4a5f54f2 [Fix] (Diligent/PSO): Avoid adding duplicate shader resources. 2025-06-09 00:25:50 +08:00
BZLZHH b73c6e749e [Fix] (Diligent/Texture): Remove useless judgement in glTexSubImage2D. 2025-06-08 23:23:23 +08:00
BZLZHH 1022a4dfc3 [Fix] (Diligent/Buffer): Update all dynamic buffers in glDraw*. 2025-06-08 23:00:13 +08:00
BZLZHH ee72f7d07f [Fix] (Diligent/Framebuffer): Make sure glBlitFramebuffer is not in renderpass. 2025-06-08 22:23:12 +08:00
swung0x48 8af2aa262b Merge branch 'Feat/Diligent' of https://github.com/MobileGL-Dev/MobileGL into feat/Diligent 2025-06-08 20:19:36 +08:00
swung0x48 40a458b743 [Fix]: save order of uniform names, and apply it at linking and buffer mapping 2025-06-08 20:19:06 +08:00
BZLZHH e645167c94 [Fix] (Diligent/PSO): Set stride value for layout element. 2025-06-08 18:56:56 +08:00
BZLZHH c183203264 [Fix] (Diligent/Drawing): Use real type for IBO. 2025-06-08 18:17:05 +08:00
BZLZHH 4dfbc01479 [Fix] (Diligent/PSO): Build InputLayout for PSO. 2025-06-08 17:29:10 +08:00
BZLZHH f3497bd2fa [Improvement] (ProgramState): Rename AttributeBindings -> AttributeLocations. 2025-06-08 16:01:31 +08:00
BZLZHH 3c98bc5eca [Improvement] (ProgramState): Remove useless programObj.attribBindings. 2025-06-08 15:54:10 +08:00
swung0x48 9640e167df [Feat] (GL_Buffer.cpp): name buffers 2025-06-08 13:46:41 +08:00
swung0x48 b580605c86 [Fix] (EGL_impl.h): get rid of redundant extern var 2025-06-08 13:45:27 +08:00
BZLZHH 292c7eeecf [Fix] (Diligent/Buffer): Create dynamic buffer in glDraw*. 2025-06-08 13:35:32 +08:00
BZLZHH 848f110658 [Fix] (DiligentEngine): Fix some miscellaneous issues. 2025-06-08 01:57:13 +08:00
BZLZHH 979d31407f [Fix] (DiligentEngine): Bind renderpass for PSO. 2025-06-08 01:04:05 +08:00
BZLZHH f5c3514dde [Fix] (Diligent/Drawing): Bind shader resources to pipeline. 2025-06-08 00:11:24 +08:00
BZLZHH beecb3dac0 [Fix] (DiligentEngine): Use SHADER_TYPE_VS_PS as stages for uniform block. 2025-06-07 23:03:12 +08:00
BZLZHH ea871e0188 [Fix] (DiligentEngine): Add static for ImmutableSamplers and Variables in ConfigureResourceLayout. 2025-06-07 22:42:38 +08:00
BZLZHH ad6b9c1ca7 [Fix] (Diligent/Texture): Fix glTexSubImage2D crashing. 2025-06-07 22:14:34 +08:00
BZLZHH 2caade5a36 [Fix] (Diligent/FrameBuffer): Remove the release of RTVs in fbo 0. 2025-06-07 22:02:30 +08:00
BZLZHH 8eb055ca81 [Fix] (Diligent/FrameBuffer): Fix UpdateDefaultFramebuffer crashing. 2025-06-07 21:15:29 +08:00
BZLZHH 852b843b4a [Fix] (Diligent/Texture): Add BIND_RENDER(/DEPTH)_TARGET for texture. 2025-06-07 20:49:48 +08:00
BZLZHH 211bf5de39 [Fix] (Diligent/Texture): Fix the 'Overwriting reference' bug in TexImage2D. 2025-06-07 20:42:25 +08:00
BZLZHH f5a14c20a9 [Feat] (DiligentEngine): Implement most rendering by DiligentEngine. 2025-06-07 19:41:32 +08:00
BZLZHH c95077f263 [Misc] (Debug): Add all gl enum constants in GLEnumToString. 2025-06-06 21:01:25 +08:00
BZLZHH ca5c1a123b Merge remote-tracking branch 'origin/dev-es' into Feat/Diligent 2025-06-05 14:03:41 +08:00
BZLZHH 6075ae1445 [Feat] (DiligentEngine): Capable to render. 2025-06-05 13:58:34 +08:00
BZLZHH 2466897531 [Feat] (Diligent): Add Diligent Vulkan backend. 2025-05-25 11:46:38 +08:00
swung0x48 604482d55c [Feat]: Making DiligentCore EGL init work 2025-05-18 20:51:58 +08:00
swung0x48 906323f219 [Misc]: bringing in DiligentCore 2025-05-17 22:47:59 +08:00
swung0x48 13022c79bf [Misc]: add DiligentCore as submodule 2025-05-17 22:11:38 +08:00
63 changed files with 7442 additions and 1532 deletions
+3
View File
@@ -3,3 +3,6 @@
################################################################################ ################################################################################
/build /build
.cxx
/.vs
/out/build
+3
View File
@@ -0,0 +1,3 @@
[submodule "3rdparty/DiligentCore"]
path = 3rdparty/DiligentCore
url = https://github.com/DiligentGraphics/DiligentCore.git
Vendored Submodule
+1
Submodule 3rdparty/DiligentCore added at f36e638805
+14 -4
View File
@@ -55,7 +55,9 @@ add_library(${CMAKE_PROJECT_NAME} SHARED
MG/MG_GL/Implementations/EGL/VK/EGL_EMU.cpp MG/MG_GL/Implementations/EGL/VK/EGL_EMU.cpp
MG/MG_GL/Implementations/EGL/GLES/EGL_WRAP.cpp MG/MG_GL/Implementations/EGL/GLES/EGL_WRAP.cpp
MG/MG_GL/Implementations/EGL/Diligent/EGL_impl.cpp
# MG_GL/State # MG_GL/State
MG/MG_GL/State/Core/GLState.cpp MG/MG_GL/State/Core/GLState.cpp
@@ -88,7 +90,7 @@ add_library(${CMAKE_PROJECT_NAME} SHARED
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE ./includes) target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE ./includes)
target_link_libraries(${CMAKE_PROJECT_NAME} target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE
${CMAKE_SOURCE_DIR}/library/arm64-v8a/libglslang.a ${CMAKE_SOURCE_DIR}/library/arm64-v8a/libglslang.a
${CMAKE_SOURCE_DIR}/library/arm64-v8a/libspirv-cross-c-shared.so ${CMAKE_SOURCE_DIR}/library/arm64-v8a/libspirv-cross-c-shared.so
#${CMAKE_SOURCE_DIR}/library/arm64-v8a/libshaderconv.so #${CMAKE_SOURCE_DIR}/library/arm64-v8a/libshaderconv.so
@@ -110,15 +112,23 @@ target_link_libraries(${CMAKE_PROJECT_NAME}
vulkan vulkan
) )
add_subdirectory(3rdparty/DiligentCore)
target_include_directories(MobileGL PUBLIC target_include_directories(MobileGL PUBLIC
${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/include
) )
target_link_libraries(MobileGL
PRIVATE
Diligent-Common
Diligent-GraphicsEngineOpenGL-shared
Diligent-GraphicsEngineVk-shared
)
if (PROFILING) if (PROFILING)
find_package(Threads) find_package(Threads)
include_directories(${CMAKE_SOURCE_DIR}/3rdparty/perfetto/sdk) include_directories(${CMAKE_SOURCE_DIR}/3rdparty/perfetto/sdk)
add_library(perfetto STATIC ${CMAKE_SOURCE_DIR}/3rdparty/perfetto/sdk/perfetto.cc) add_library(perfetto STATIC ${CMAKE_SOURCE_DIR}/3rdparty/perfetto/sdk/perfetto.cc)
target_link_libraries(MobileGL perfetto ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries(MobileGL PRIVATE perfetto ${CMAKE_THREAD_LIBS_INIT})
target_compile_definitions(MobileGL PUBLIC PROFILING=1) target_compile_definitions(MobileGL PUBLIC PROFILING=1)
endif() endif()
+42 -27
View File
@@ -21,20 +21,20 @@
#define MG_EXPORT extern "C" __attribute__((visibility("default"))) #define MG_EXPORT extern "C" __attribute__((visibility("default")))
#endif #endif
namespace ankerl { namespace MG_Global {
template <typename K, typename V> template<typename K, typename V>
using unordered_map = ankerl::unordered_dense::map<K, V>; using unordered_map = ankerl::unordered_dense::map<K, V>;
template <typename T> template<typename T>
using unordered_set = ankerl::unordered_dense::set<T>; using unordered_set = ankerl::unordered_dense::set<T>;
} }
namespace MG_Constants { namespace MG_Constants {
namespace Common { namespace Common {
inline constexpr int LOG_LEVEL_DEBUG = 0x0010; inline constexpr int LOG_LEVEL_DEBUG = 0x0010;
inline constexpr int LOG_LEVEL_WARN = 0x0011; inline constexpr int LOG_LEVEL_INFO = 0x0011;
inline constexpr int LOG_LEVEL_ERROR = 0x0012; inline constexpr int LOG_LEVEL_WARN = 0x0012;
inline constexpr int LOG_LEVEL_INFO = 0x0013; inline constexpr int LOG_LEVEL_ERROR = 0x0013;
inline constexpr int LOG_LEVEL_FATAL = 0x0014; inline constexpr int LOG_LEVEL_FATAL = 0x0014;
@@ -43,10 +43,15 @@ namespace MG_Constants {
inline constexpr int LOG_TARGET_FILE = 0x02; inline constexpr int LOG_TARGET_FILE = 0x02;
inline constexpr int LOG_TARGET_ANDROID = 0x04; // Android logcat inline constexpr int LOG_TARGET_ANDROID = 0x04; // Android logcat
inline constexpr int LOG_TARGET_ALL = LOG_TARGET_CONSOLE | LOG_TARGET_FILE | LOG_TARGET_ANDROID; inline constexpr int LOG_TARGET_ALL = LOG_TARGET_CONSOLE | LOG_TARGET_FILE | LOG_TARGET_ANDROID;
template <typename T>
bool Contains(T item, const std::vector<T> vec) {
return std::find(vec.begin(), vec.end(), item) != vec.end();
}
} }
namespace Blend { namespace Blend {
static const ankerl::unordered_set<GLenum> VALID_FACTORS = { static const std::vector<GLenum> VALID_FACTORS = {
GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR,
GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR, GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR,
@@ -55,51 +60,55 @@ namespace MG_Constants {
} }
namespace Depth { namespace Depth {
static const ankerl::unordered_set<GLenum> VALID_FUNCS = { static const std::vector<GLenum> VALID_FUNCS = {
GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL, GL_GREATER, GL_NOTEQUAL, GL_GEQUAL, GL_ALWAYS GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL, GL_GREATER, GL_NOTEQUAL, GL_GEQUAL, GL_ALWAYS
}; // OpenGL 3 }; // OpenGL 3
} }
namespace CommonState { namespace CommonState {
static const ankerl::unordered_set<GLenum> VALID_CAPS = { static const std::vector<GLenum> VALID_CAPS = {
GL_BLEND, GL_DEPTH_TEST, GL_STENCIL_TEST, GL_SCISSOR_TEST, GL_CULL_FACE, GL_BLEND, GL_DEPTH_TEST, GL_STENCIL_TEST, GL_SCISSOR_TEST, GL_CULL_FACE,
GL_POLYGON_OFFSET_FILL, GL_SAMPLE_ALPHA_TO_COVERAGE, GL_SAMPLE_COVERAGE GL_POLYGON_OFFSET_FILL, GL_SAMPLE_ALPHA_TO_COVERAGE, GL_SAMPLE_COVERAGE
}; // OpenGL 3 }; // OpenGL 3
} }
namespace Framebuffer { namespace Framebuffer {
static const ankerl::unordered_set<GLenum> VALID_ATTACHMENTS = { static const std::vector<GLenum> VALID_ATTACHMENTS = {
GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT,
GL_STENCIL_ATTACHMENT, GL_DEPTH_STENCIL_ATTACHMENT GL_STENCIL_ATTACHMENT, GL_DEPTH_STENCIL_ATTACHMENT
}; // OpenGL 3 }; // OpenGL 3
static const ankerl::unordered_set<GLenum> VALID_TARGETS = { static const std::vector<GLenum> VALID_TARGETS = {
GL_FRAMEBUFFER, GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER GL_FRAMEBUFFER, GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER
}; // OpenGL 3 }; // OpenGL 3
static const ankerl::unordered_set<GLenum> VALID_ACCESS = { static const std::vector<GLenum> VALID_ACCESS = {
GL_READ_ONLY, GL_WRITE_ONLY, GL_READ_WRITE GL_READ_ONLY, GL_WRITE_ONLY, GL_READ_WRITE
}; // OpenGL 3 }; // OpenGL 3
} }
namespace Buffer { namespace Buffer {
static const ankerl::unordered_set<GLenum> VALID_PARAM_NAMES = { static const std::vector<GLenum> VALID_PARAM_NAMES = {
GL_BUFFER_ACCESS, GL_BUFFER_MAPPED, GL_BUFFER_SIZE, GL_BUFFER_USAGE GL_BUFFER_ACCESS, GL_BUFFER_MAPPED, GL_BUFFER_SIZE, GL_BUFFER_USAGE
}; // OpenGL 3 }; // OpenGL 3
static const ankerl::unordered_set<GLenum> VALID_TARGETS = { static const std::vector<GLenum> VALID_TARGETS = {
GL_ARRAY_BUFFER, GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, GL_ELEMENT_ARRAY_BUFFER, GL_ARRAY_BUFFER, GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, GL_ELEMENT_ARRAY_BUFFER,
GL_PIXEL_PACK_BUFFER, GL_PIXEL_UNPACK_BUFFER, GL_TEXTURE_BUFFER, GL_PIXEL_PACK_BUFFER, GL_PIXEL_UNPACK_BUFFER, GL_TEXTURE_BUFFER,
GL_TRANSFORM_FEEDBACK_BUFFER, GL_UNIFORM_BUFFER GL_TRANSFORM_FEEDBACK_BUFFER, GL_UNIFORM_BUFFER
}; // OpenGL 3 }; // OpenGL 3
static const ankerl::unordered_set<GLenum> VALID_ACCESS = { static const std::vector<GLenum> VALID_ACCESS = {
GL_READ_ONLY, GL_WRITE_ONLY, GL_READ_WRITE GL_READ_ONLY, GL_WRITE_ONLY, GL_READ_WRITE
}; // OpenGL 3 }; // OpenGL 3
} }
namespace VertexArray {
constexpr uint32_t MAX_VERTEX_ATTRIBS = 32;
}
namespace PixelStore { namespace PixelStore {
static const ankerl::unordered_map<GLenum, GLint> DEFAULT_VALUES_MAP = { static const MG_Global::unordered_map<GLenum, GLint> DEFAULT_VALUES_MAP = {
{GL_PACK_SWAP_BYTES, GL_FALSE}, {GL_PACK_SWAP_BYTES, GL_FALSE},
{GL_PACK_LSB_FIRST, GL_FALSE}, {GL_PACK_LSB_FIRST, GL_FALSE},
{GL_PACK_ROW_LENGTH, 0}, {GL_PACK_ROW_LENGTH, 0},
@@ -118,7 +127,7 @@ namespace MG_Constants {
{GL_UNPACK_ALIGNMENT, 4} {GL_UNPACK_ALIGNMENT, 4}
}; // OpenGL 3 }; // OpenGL 3
static const ankerl::unordered_set<GLenum> VALID_PARAM_NAMES = { static const std::vector<GLenum> VALID_PARAM_NAMES = {
GL_PACK_SWAP_BYTES, GL_PACK_LSB_FIRST, GL_PACK_ROW_LENGTH, GL_PACK_IMAGE_HEIGHT, GL_PACK_SWAP_BYTES, GL_PACK_LSB_FIRST, GL_PACK_ROW_LENGTH, GL_PACK_IMAGE_HEIGHT,
GL_PACK_SKIP_ROWS, GL_PACK_SKIP_PIXELS, GL_PACK_SKIP_IMAGES, GL_PACK_ALIGNMENT, GL_PACK_SKIP_ROWS, GL_PACK_SKIP_PIXELS, GL_PACK_SKIP_IMAGES, GL_PACK_ALIGNMENT,
GL_UNPACK_SWAP_BYTES, GL_UNPACK_LSB_FIRST, GL_UNPACK_ROW_LENGTH, GL_UNPACK_SWAP_BYTES, GL_UNPACK_LSB_FIRST, GL_UNPACK_ROW_LENGTH,
@@ -132,18 +141,18 @@ namespace MG_Constants {
inline const GLuint MAX_TEXTURE_UNITS = 80; inline const GLuint MAX_TEXTURE_UNITS = 80;
const GLsizei MAX_TEXTURE_SIZE = 32768; const GLsizei MAX_TEXTURE_SIZE = 32768;
const GLsizei MAX_ARRAY_LAYERS = 256; const GLsizei MAX_ARRAY_LAYERS = 256;
inline const ankerl::unordered_set<GLenum> VALID_TARGETS = { inline const std::vector<GLenum> VALID_TARGETS = {
GL_TEXTURE_2D, GL_PROXY_TEXTURE_2D, GL_TEXTURE_1D_ARRAY, GL_PROXY_TEXTURE_1D_ARRAY, GL_TEXTURE_2D, GL_PROXY_TEXTURE_2D, GL_TEXTURE_1D_ARRAY, GL_PROXY_TEXTURE_1D_ARRAY,
GL_TEXTURE_RECTANGLE, GL_PROXY_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_RECTANGLE, GL_PROXY_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, GL_PROXY_TEXTURE_CUBE_MAP GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, GL_PROXY_TEXTURE_CUBE_MAP
}; // OpenGL 3 }; // OpenGL 3
inline const ankerl::unordered_set<GLenum> VALID_FORMATS = { inline const std::vector<GLenum> VALID_FORMATS = {
GL_RED, GL_RG, GL_RGB, GL_BGR, GL_RGBA, GL_BGRA, GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL GL_RED, GL_RG, GL_RGB, GL_BGR, GL_RGBA, GL_BGRA, GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL
}; // OpenGL 3 }; // OpenGL 3
inline const ankerl::unordered_set<GLenum> VALID_INTERNAL_FORMATS = { inline const std::vector<GLenum> VALID_INTERNAL_FORMATS = {
GL_RED, GL_RG, GL_RGB, GL_BGR, GL_RGBA, GL_BGRA, GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL, GL_RED, GL_RG, GL_RGB, GL_BGR, GL_RGBA, GL_BGRA, GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL,
GL_RGBA32F, GL_RGBA32I, GL_RGBA32UI, GL_RGBA16, GL_RGBA16F, GL_RGBA16I, GL_RGBA32F, GL_RGBA32I, GL_RGBA32UI, GL_RGBA16, GL_RGBA16F, GL_RGBA16I,
GL_RGBA16UI, GL_RGBA8, GL_RGBA8UI, GL_SRGB8_ALPHA8, GL_RGB10_A2, GL_RGB10_A2UI, GL_RGBA16UI, GL_RGBA8, GL_RGBA8UI, GL_SRGB8_ALPHA8, GL_RGB10_A2, GL_RGB10_A2UI,
@@ -158,7 +167,7 @@ namespace MG_Constants {
GL_DEPTH32F_STENCIL8, GL_DEPTH24_STENCIL8 GL_DEPTH32F_STENCIL8, GL_DEPTH24_STENCIL8
}; // OpenGL 3 }; // OpenGL 3
inline const ankerl::unordered_set<GLenum> VALID_TYPES = { inline const std::vector<GLenum> VALID_TYPES = {
GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT, GL_UNSIGNED_INT, GL_INT, GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT, GL_UNSIGNED_INT, GL_INT,
GL_FLOAT, GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, GL_UNSIGNED_SHORT_5_6_5, GL_FLOAT, GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, GL_UNSIGNED_SHORT_5_6_5,
GL_UNSIGNED_SHORT_5_6_5_REV, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, GL_UNSIGNED_SHORT_5_6_5_REV, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV,
@@ -166,14 +175,14 @@ namespace MG_Constants {
GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, GL_UNSIGNED_INT_2_10_10_10_REV GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, GL_UNSIGNED_INT_2_10_10_10_REV
}; // OpenGL 3 }; // OpenGL 3
inline const ankerl::unordered_set<GLenum> VALID_TEXTURE_PARAM_NAMES = { inline const std::vector<GLenum> VALID_TEXTURE_PARAM_NAMES = {
GL_TEXTURE_BASE_LEVEL, GL_TEXTURE_COMPARE_FUNC, GL_TEXTURE_COMPARE_MODE, GL_TEXTURE_MIN_FILTER, GL_TEXTURE_BASE_LEVEL, GL_TEXTURE_COMPARE_FUNC, GL_TEXTURE_COMPARE_MODE, GL_TEXTURE_MIN_FILTER,
GL_TEXTURE_MAG_FILTER, GL_TEXTURE_MAX_LEVEL, GL_TEXTURE_SWIZZLE_R, GL_TEXTURE_SWIZZLE_G, GL_TEXTURE_MAG_FILTER, GL_TEXTURE_MAX_LEVEL, GL_TEXTURE_SWIZZLE_R, GL_TEXTURE_SWIZZLE_G,
GL_TEXTURE_SWIZZLE_B, GL_TEXTURE_SWIZZLE_A, GL_TEXTURE_SWIZZLE_RGBA, GL_TEXTURE_WRAP_S, GL_TEXTURE_SWIZZLE_B, GL_TEXTURE_SWIZZLE_A, GL_TEXTURE_SWIZZLE_RGBA, GL_TEXTURE_WRAP_S,
GL_TEXTURE_WRAP_T, GL_TEXTURE_WRAP_R, GL_TEXTURE_LOD_BIAS, GL_TEXTURE_MIN_LOD, GL_TEXTURE_MAX_LOD, GL_TEXTURE_BORDER_COLOR GL_TEXTURE_WRAP_T, GL_TEXTURE_WRAP_R, GL_TEXTURE_LOD_BIAS, GL_TEXTURE_MIN_LOD, GL_TEXTURE_MAX_LOD, GL_TEXTURE_BORDER_COLOR
}; // OpenGL 3 }; // OpenGL 3
inline const ankerl::unordered_set<GLenum> VALID_QUERY_LEVEL_PROPERTY_PARAM_NAMES = { inline const std::vector<GLenum> VALID_QUERY_LEVEL_PROPERTY_PARAM_NAMES = {
GL_TEXTURE_WIDTH, GL_TEXTURE_HEIGHT, GL_TEXTURE_DEPTH, GL_TEXTURE_INTERNAL_FORMAT, GL_TEXTURE_WIDTH, GL_TEXTURE_HEIGHT, GL_TEXTURE_DEPTH, GL_TEXTURE_INTERNAL_FORMAT,
GL_TEXTURE_RED_SIZE, GL_TEXTURE_GREEN_SIZE, GL_TEXTURE_BLUE_SIZE, GL_TEXTURE_ALPHA_SIZE, GL_TEXTURE_RED_SIZE, GL_TEXTURE_GREEN_SIZE, GL_TEXTURE_BLUE_SIZE, GL_TEXTURE_ALPHA_SIZE,
GL_TEXTURE_DEPTH_SIZE, GL_TEXTURE_COMPRESSED, GL_TEXTURE_COMPRESSED_IMAGE_SIZE GL_TEXTURE_DEPTH_SIZE, GL_TEXTURE_COMPRESSED, GL_TEXTURE_COMPRESSED_IMAGE_SIZE
@@ -181,9 +190,15 @@ namespace MG_Constants {
} }
namespace Backend { namespace Backend {
#define BACKEND_VULKAN 0x0015 #define BACKEND_VULKAN 0x0015
#define BACKEND_METAL 0x0016 #define BACKEND_METAL 0x0016
#define BACKEND_GLES 0x0017 #define BACKEND_GLES 0x0017
#define BACKEND_DILIGENT 0x0018
inline const int BACKEND_DILIGENT_VULKAN = 0x0020;
inline const int BACKEND_DILIGENT_METAL = 0x0021; // not ready currently
inline const int BACKEND_DILIGENT_OPENGL = 0x0022;
} }
inline const char* RenderName = "MobileGL"; inline const char* RenderName = "MobileGL";
+47 -78
View File
@@ -1,85 +1,9 @@
// //
// Created by BZLZHH on 2025/3/15. // Created by BZLZHH on 2025/3/15.
// //
#pragma once
#include "Constants.h" #define BACKEND_TYPE BACKEND_DILIGENT
#define BACKEND_TYPE BACKEND_GLES
#include "Global.h"
#ifndef MOBILEGL_GLES_LOADER_H
#include "MG_GL/BackendLoader/GLES/Loader.h"
#endif
#ifndef MOBILEGL_GL_FRAMEBUFFER_H
#include "MG_GL/Implementations/GL/Framebuffer/GL_Framebuffer.h"
#endif
#ifndef MOBILEGL_GL_GETTER_H
#include "MG_GL/Implementations/GL/Getter/GL_Getter.h"
#endif
#ifndef MOBILEGL_BACKENDINFO_H
#include "MG_GL/Implementations/GL/Getter/BackendInfo.h"
#endif
#ifndef MOBILEGL_GL_BUFFER_H
#include "MG_GL/Implementations/GL/Buffer/GL_Buffer.h"
#endif
#ifndef MOBILEGL_GL_DRAWING_H
#include "MG_GL/Implementations/GL/Drawing/GL_Drawing.h"
#endif
#ifndef MOBILEGL_GL_PROGRAM_H
#include "MG_GL/Implementations/GL/Program/GL_Program.h"
#endif
#ifndef MOBILEGL_GL_TEXTURE_H
#include "MG_GL/Implementations/GL/Texture/GL_Texture.h"
#endif
#ifndef MOBILEGL_GL_VERTEXARRAY_H
#include "MG_GL/Implementations/GL/VertexArray/GL_VertexArray.h"
#endif
#ifndef MOBILEGL_GLSTATE_H
#include "MG_GL/State/Core/GLState.h"
#endif
#ifndef MOBILEGL_COMMONSTATE_H
#include "MG_GL/State/Common/CommonState.h"
#endif
#ifndef MOBILEGL_TEXTURESTATE_H
#include "MG_GL/State/Texture/TextureState.h"
#endif
#ifndef MOBILEGL_VERTEXARRAYSTATE_H
#include "MG_GL/State/VertexArray/VertexArrayState.h"
#endif
#ifndef MOBILEGL_BUFFERSTATE_H
#include "MG_GL/State/Buffer/BufferState.h"
#endif
#ifndef MOBILEGL_SHADEROBJECT_H
#include "MG_GL/State/Program/ShaderObject.h"
#endif
#ifndef MOBILEGL_PROGRAMSTATE_H
#include "MG_GL/State/Program/ProgramState.h"
#endif
#ifndef MOBILEGL_FRAMEBUFFERSTATE_H
#include "MG_GL/State/Framebuffer/FramebufferState.h"
#endif
#ifndef MOBILEGL_LOOKUP_H
#include "MG_GL/Implementations/GLX/LookUp/LookUp.h"
#endif
#ifndef MOBILEGL_DEBUG_H
#include "MG_UTIL/Debug/Debug.h"
#endif
#ifndef MOBILEGL_GLSLTOOL_H
#include "MG_UTIL/Program/GLSLTool.h"
#endif
#ifndef MOBILEGL_PROGRAM_DEBUGTOOL_H
#include "MG_UTIL/Program/DebugTool.h"
#endif
#ifndef MOBILEGL_GL_COMMON_H
#include "MG_GL/Implementations/GL/Common/GL_Common.h"
#endif
#ifndef MOBILEGL_EGL_VK_EMU_H
#include "MG_GL/Implementations/EGL/VK/EGL_EMU.h"
#endif
#ifndef MOBILEGL_EGL_GLES_EGL_WRAP_H
#include "MG_GL/Implementations/EGL/GLES/EGL_WRAP.h"
#endif
#ifndef MOBILEGL_TESTDRAWING_H
#include "MG_RHI/GLES/Test/TestDrawing.h"
#endif
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
@@ -90,6 +14,7 @@
#include <string> #include <string>
#include <map> #include <map>
#include <vector> #include <vector>
#include <cctype>
#include <stdexcept> #include <stdexcept>
#include <atomic> #include <atomic>
#include <regex> #include <regex>
@@ -101,6 +26,7 @@
#include <unordered_map> #include <unordered_map>
#include <queue> #include <queue>
#include <format> #include <format>
#include <memory>
#include <glslang/Public/ShaderLang.h> #include <glslang/Public/ShaderLang.h>
#include <glslang/Include/Types.h> #include <glslang/Include/Types.h>
#include <glslang/Public/ShaderLang.h> #include <glslang/Public/ShaderLang.h>
@@ -112,6 +38,7 @@
#include <GLES3/gl32.h> #include <GLES3/gl32.h>
#include "MG_Include/UncertainBool.hpp" #include "MG_Include/UncertainBool.hpp"
#include "MG_Include/IndexGenerator.hpp"
#ifdef _WIN32 #ifdef _WIN32
#include <Windows.h> #include <Windows.h>
@@ -138,3 +65,45 @@
#include <EGL/egl.h> #include <EGL/egl.h>
#include <GL/gl.h> #include <GL/gl.h>
#include <GL/glext.h> #include <GL/glext.h>
#if BACKEND_TYPE == BACKEND_DILIGENT
#include "EngineFactory.h"
#include "EngineFactoryOpenGL.h"
#include "EngineFactoryVk.h"
#include "RefCntAutoPtr.hpp"
#include "PipelineState.h"
#include "GraphicsTypes.h"
#include "DeviceContext.h"
#endif
#include "Constants.h"
#include "Global.h"
#include "MG_GL/Implementations/EGL/Diligent/DiligentConfig.h"
#include "MG_GL/BackendLoader/GLES/Loader.h"
#include "MG_GL/Implementations/GL/Framebuffer/GL_Framebuffer.h"
#include "MG_GL/Implementations/GL/Getter/GL_Getter.h"
#include "MG_GL/Implementations/GL/Getter/BackendInfo.h"
#include "MG_GL/Implementations/GL/Buffer/GL_Buffer.h"
#include "MG_GL/Implementations/GL/Drawing/GL_Drawing.h"
#include "MG_GL/Implementations/GL/Program/GL_Program.h"
#include "MG_GL/Implementations/GL/Texture/GL_Texture.h"
#include "MG_GL/Implementations/GL/VertexArray/GL_VertexArray.h"
#include "MG_GL/State/Common/CommonState.h"
#include "MG_GL/State/Texture/TextureState.h"
#include "MG_GL/State/VertexArray/VertexArrayState.h"
#include "MG_GL/State/Buffer/BufferState.h"
#include "MG_GL/State/Program/ShaderObject.h"
#include "MG_GL/State/Program/ProgramState.h"
#include "MG_GL/State/Framebuffer/FramebufferState.h"
#include "MG_GL/State/Core/GLState.h"
#include "MG_GL/Implementations/EGL/Diligent/EGL_impl.h"
#include "MG_GL/Implementations/GLX/LookUp/LookUp.h"
#include "MG_UTIL/Debug/Debug.h"
#include "MG_UTIL/Program/GLSLTool.h"
#include "MG_UTIL/Program/DebugTool.h"
#include "MG_GL/Implementations/GL/Common/GL_Common.h"
#include "MG_GL/Implementations/EGL/VK/EGL_EMU.h"
#include "MG_GL/Implementations/EGL/GLES/EGL_WRAP.h"
#include "MG_RHI/GLES/Test/TestDrawing.h"
+2
View File
@@ -8,7 +8,9 @@ void MG_Initialize() {
MG_Util::Debug::LogInit(); MG_Util::Debug::LogInit();
MG_Util::Debug::LogI("MobileGL Initializing..."); MG_Util::Debug::LogI("MobileGL Initializing...");
MG_State::Init(); MG_State::Init();
#if BACKEND_TYPE == BACKEND_GLES
MG_GL::BackendLoader::Init(); MG_GL::BackendLoader::Init();
#endif
} }
void MG_Destroy() { void MG_Destroy() {
+1 -1
View File
@@ -2,7 +2,7 @@
// Created by BZLZHH on 2025/4/26. // Created by BZLZHH on 2025/4/26.
// //
#include "Loader.h" #include "../../../Includes.h"
#if BACKEND_TYPE == BACKEND_GLES #if BACKEND_TYPE == BACKEND_GLES
-2
View File
@@ -5,8 +5,6 @@
#ifndef MOBILEGL_GLES_LOADER_H #ifndef MOBILEGL_GLES_LOADER_H
#define MOBILEGL_GLES_LOADER_H #define MOBILEGL_GLES_LOADER_H
#include "../../../Includes.h"
#if BACKEND_TYPE == BACKEND_GLES #if BACKEND_TYPE == BACKEND_GLES
#define APIENTRY_GLES #define APIENTRY_GLES
@@ -0,0 +1,9 @@
//
// Created by BZLZHH on 2025/5/25.
//
#pragma once
namespace MG_Diligent {
inline const int DILIGENT_BACKEND_TYPE = MG_Constants::Backend::BACKEND_DILIGENT_VULKAN;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,264 @@
//
// Created by Swung 0x48 on 2025-05-18.
//
#ifndef MOBILEGL_DILIGENT_EGL_IMPL_H
#define MOBILEGL_DILIGENT_EGL_IMPL_H
#if BACKEND_TYPE == BACKEND_DILIGENT
namespace MG_Diligent {
extern Diligent::IRenderDevice* g_pDevice;
extern Diligent::IDeviceContext* g_pContext;
extern Diligent::ISwapChain* g_pSwapChain;
extern MG_Global::unordered_map<GLuint, Diligent::IBuffer*> g_BufferMap;
extern MG_Global::unordered_map<GLuint, Diligent::ITexture*> g_TextureMap;
extern MG_Global::unordered_map<GLuint, Diligent::ITextureView*> g_TextureViewMap;
struct GLFramebufferInfo
{
// Diligent::IFramebuffer* pFramebuffer = nullptr;
// Diligent::IRenderPass* pRenderPass = nullptr;
std::vector<Diligent::ITextureView*> ColorRTVs;
Diligent::ITextureView* pDepthStencilRTV = nullptr;
Diligent::TEXTURE_FORMAT DepthStencilFormat = Diligent::TEX_FORMAT_UNKNOWN;
bool HasDepthStencil = false;
std::vector<Diligent::OptimizedClearValue> ClearValues;
// ...
};
extern MG_Global::unordered_map<GLuint, GLFramebufferInfo> g_FramebufferMap;
extern MG_Global::unordered_map<GLuint, Diligent::IShader*> g_ShaderMap;
struct GLProgramInfo
{
GLuint id;
std::vector<Diligent::IShader*> AttachedShaders;
std::vector<GLuint> AttachedShadersID;
Diligent::IPipelineState* pPipelineState = nullptr;
Diligent::IShaderResourceBinding* pResourceBinding = nullptr;
uint64_t psoStateHash = 0;
bool psoDirty = true;
std::vector<Diligent::LayoutElement> inputLayout;
GLuint DefaultFBO = 0;
ProgramObject programObj;
// Uniform names, in the order of their index in uniform buffer
std::vector<std::string> uniformBufferNames;
Diligent::IBuffer* pDefaultUBO = nullptr;
std::unordered_map<std::string, Diligent::SHADER_TYPE> uniformStages;
std::unordered_map<std::string, size_t> uniformOffsets;
// ...
};
extern MG_Global::unordered_map<GLuint, GLProgramInfo> g_ProgramMap;
extern MG_Global::unordered_map<GLuint, Diligent::ISampler*> g_SamplerMap;
extern MG_Global::unordered_map<GLuint, Diligent::IBuffer*> g_UniformBufferMap;
extern Diligent::IBuffer* g_TriangleFanIndexBuffer;
inline Diligent::PRIMITIVE_TOPOLOGY GLPrimitiveTopologyToDiligent(GLenum Topology)
{
switch (Topology)
{
case GL_TRIANGLE_STRIP:
return Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
case GL_TRIANGLES:
return Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
case GL_TRIANGLE_FAN:
return Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
// TODO: Handle other topologies
default:
return Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
}
}
class PipelineStateManager {
private:
struct PSOKey {
uint64_t programHash;
uint64_t stateHash;
bool operator==(const PSOKey &other) const {
return programHash == other.programHash && stateHash == other.stateHash;
}
};
struct PSOKeyHash {
size_t operator()(const PSOKey &key) const {
return std::hash<uint64_t>()(key.programHash) ^
std::hash<uint64_t>()(key.stateHash);
}
};
std::unordered_map<PSOKey, Diligent::IPipelineState *, PSOKeyHash> psoCache;
public:
Diligent::IPipelineState *GetOrCreatePSO(
GLuint program,
GLProgramInfo &programInfo,
CommonState &commonState,
VertexArrayState &vaState,
GLFramebufferInfo& fbInfo,
GLenum primitiveTopology);
void MarkPSODirty(GLuint program);
void ReleasePSO(GLuint program);
private:
Diligent::FILTER_TYPE ConvertGLFilter(GLenum filter) {
switch (filter) {
case GL_NEAREST:
case GL_NEAREST_MIPMAP_NEAREST:
case GL_NEAREST_MIPMAP_LINEAR:
return Diligent::FILTER_TYPE_POINT;
case GL_LINEAR:
case GL_LINEAR_MIPMAP_NEAREST:
case GL_LINEAR_MIPMAP_LINEAR:
return Diligent::FILTER_TYPE_LINEAR;
default:
return Diligent::FILTER_TYPE_LINEAR;
}
}
Diligent::FILTER_TYPE ConvertGLMipFilter(GLenum filter) {
switch (filter) {
case GL_NEAREST_MIPMAP_NEAREST:
case GL_LINEAR_MIPMAP_NEAREST:
return Diligent::FILTER_TYPE_POINT;
case GL_NEAREST_MIPMAP_LINEAR:
case GL_LINEAR_MIPMAP_LINEAR:
return Diligent::FILTER_TYPE_LINEAR;
case GL_NEAREST:
case GL_LINEAR:
return Diligent::FILTER_TYPE_LINEAR;
default:
return Diligent::FILTER_TYPE_LINEAR;
}
}
Diligent::TEXTURE_ADDRESS_MODE ConvertGLWrapMode(GLenum wrap) {
switch (wrap) {
case GL_REPEAT:
return Diligent::TEXTURE_ADDRESS_WRAP;
case GL_MIRRORED_REPEAT:
return Diligent::TEXTURE_ADDRESS_MIRROR;
case GL_CLAMP_TO_EDGE:
return Diligent::TEXTURE_ADDRESS_CLAMP;
case GL_CLAMP_TO_BORDER:
return Diligent::TEXTURE_ADDRESS_BORDER;
case GL_MIRROR_CLAMP_TO_EDGE:
return Diligent::TEXTURE_ADDRESS_MIRROR_ONCE;
default:
return Diligent::TEXTURE_ADDRESS_WRAP;
}
}
Diligent::BLEND_FACTOR ConvertGLBlendFactor(GLenum factor) {
switch (factor) {
case GL_ZERO:
return Diligent::BLEND_FACTOR_ZERO;
case GL_ONE:
return Diligent::BLEND_FACTOR_ONE;
case GL_SRC_COLOR:
return Diligent::BLEND_FACTOR_SRC_COLOR;
case GL_ONE_MINUS_SRC_COLOR:
return Diligent::BLEND_FACTOR_INV_SRC_COLOR;
case GL_DST_COLOR:
return Diligent::BLEND_FACTOR_DEST_COLOR;
case GL_ONE_MINUS_DST_COLOR:
return Diligent::BLEND_FACTOR_INV_DEST_COLOR;
case GL_SRC_ALPHA:
return Diligent::BLEND_FACTOR_SRC_ALPHA;
case GL_ONE_MINUS_SRC_ALPHA:
return Diligent::BLEND_FACTOR_INV_SRC_ALPHA;
case GL_DST_ALPHA:
return Diligent::BLEND_FACTOR_DEST_ALPHA;
case GL_ONE_MINUS_DST_ALPHA:
return Diligent::BLEND_FACTOR_INV_DEST_ALPHA;
default:
return Diligent::BLEND_FACTOR_ONE;
}
}
Diligent::COMPARISON_FUNCTION ConvertGLDepthFunc(GLenum func) {
switch (func) {
case GL_LESS:
return Diligent::COMPARISON_FUNC_LESS;
case GL_LEQUAL:
return Diligent::COMPARISON_FUNC_LESS_EQUAL;
case GL_GREATER:
return Diligent::COMPARISON_FUNC_GREATER;
case GL_GEQUAL:
return Diligent::COMPARISON_FUNC_GREATER_EQUAL;
case GL_EQUAL:
return Diligent::COMPARISON_FUNC_EQUAL;
case GL_NOTEQUAL:
return Diligent::COMPARISON_FUNC_NOT_EQUAL;
case GL_ALWAYS:
return Diligent::COMPARISON_FUNC_ALWAYS;
case GL_NEVER:
return Diligent::COMPARISON_FUNC_NEVER;
default:
return Diligent::COMPARISON_FUNC_LESS;
}
}
uint64_t CalculateStateHash(
CommonState &commonState,
VertexArrayState &vaState,
GLFramebufferInfo& fbInfo,
GLenum primitiveTopology);
void ConfigurePSO(
Diligent::GraphicsPipelineStateCreateInfo &PSOCreateInfo,
GLProgramInfo &programInfo,
CommonState &commonState,
VertexArrayState &vaState,
GLFramebufferInfo& fbInfo,
GLenum primitiveTopology);
void ConfigureResourceLayout(
Diligent::GraphicsPipelineStateCreateInfo& PSOCreateInfo,
GLProgramInfo& programInfo);
};
extern PipelineStateManager g_PSOManager;
void BuildInputLayout(GLuint program, VertexArrayState& vaState,
std::vector<Diligent::LayoutElement>& inputLayout);
extern bool initialized;
// extern bool IsInRenderPass;
extern GLuint g_NextResourceId;
}
namespace MG_EGL::Diligent {
EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint* attrib_list);
EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint* attrib_list, EGLConfig* configs, EGLint config_size, EGLint* num_config);
EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext shareCtx, const EGLint* attrib_list);
EGLBoolean eglInitialize(EGLDisplay dpy, EGLint* major, EGLint* minor);
EGLDisplay eglGetDisplay(NativeDisplayType display);
EGLint eglGetError();
EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx);
EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface);
EGLBoolean eglTerminate(EGLDisplay dpy);
EGLBoolean eglReleaseThread(void);
EGLContext eglGetCurrentContext(void);
EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
EGLBoolean eglBindAPI(EGLenum api);
EGLSurface eglGetCurrentSurface(EGLint readdraw);
EGLBoolean eglQuerySurface(EGLDisplay display, EGLSurface surface, EGLint attribute, EGLint *value);
EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval);
EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw);
EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
}
MG_EXPORT __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname);
#endif
#endif //MOBILEGL_DILIGENT_EGL_IMPL_H
@@ -2,7 +2,7 @@
// Created by BZLZHH on 2025/4/26. // Created by BZLZHH on 2025/4/26.
// //
#include "EGL_WRAP.h" #include "../../../../Includes.h"
#if BACKEND_TYPE == BACKEND_GLES #if BACKEND_TYPE == BACKEND_GLES
@@ -48,7 +48,12 @@ MG_EXPORT EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint
MG_EXPORT EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list) { MG_EXPORT EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list) {
LOAD_EGL(eglCreateWindowSurface) LOAD_EGL(eglCreateWindowSurface)
return egl_eglCreateWindowSurface(dpy, config, win, attrib_list); EGLSurface surface = egl_eglCreateWindowSurface(dpy, config, win, attrib_list);
// auto* pFactoryOpenGL = GetEngineFactoryOpenGL();
return surface;
} }
MG_EXPORT EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) { MG_EXPORT EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) {
+2 -2
View File
@@ -5,10 +5,10 @@
#ifndef MOBILEGL_EGL_GLES_EGL_WRAP_H #ifndef MOBILEGL_EGL_GLES_EGL_WRAP_H
#define MOBILEGL_EGL_GLES_EGL_WRAP_H #define MOBILEGL_EGL_GLES_EGL_WRAP_H
#include "../../../../Includes.h"
#if BACKEND_TYPE == BACKEND_GLES #if BACKEND_TYPE == BACKEND_GLES
#endif #endif
#endif //MOBILEGL_EGL_GLES_EGL_WRAP_H #endif //MOBILEGL_EGL_GLES_EGL_WRAP_H
+4 -4
View File
@@ -2,7 +2,7 @@
// Created by BZLZHH on 2025/3/30. // Created by BZLZHH on 2025/3/30.
// //
#include "EGL_EMU.h" #include "../../../../Includes.h"
#if BACKEND_TYPE == BACKEND_VULKAN #if BACKEND_TYPE == BACKEND_VULKAN
@@ -11,9 +11,9 @@ std::atomic<uintptr_t> g_nextSurfaceId{1};
EGLenum g_currentAPI = EGL_OPENGL_ES_API; EGLenum g_currentAPI = EGL_OPENGL_ES_API;
std::mutex g_globalMutex; std::mutex g_globalMutex;
ankerl::unordered_map<EGLDisplay, VulkanDisplay> g_displays; MG_Global::unordered_map<EGLDisplay, VulkanDisplay> g_displays;
ankerl::unordered_map<EGLSurface, VulkanSurface> g_surfaces; MG_Global::unordered_map<EGLSurface, VulkanSurface> g_surfaces;
ankerl::unordered_map<EGLContext, VulkanContext> g_contexts; MG_Global::unordered_map<EGLContext, VulkanContext> g_contexts;
EGLint g_lastError = EGL_SUCCESS; EGLint g_lastError = EGL_SUCCESS;
thread_local EGLContext tls_currentContext = EGL_NO_CONTEXT; thread_local EGLContext tls_currentContext = EGL_NO_CONTEXT;
+3 -5
View File
@@ -5,8 +5,6 @@
#ifndef MOBILEGL_EGL_VK_EMU_H #ifndef MOBILEGL_EGL_VK_EMU_H
#define MOBILEGL_EGL_VK_EMU_H #define MOBILEGL_EGL_VK_EMU_H
#include "../../../../Includes.h"
#if BACKEND_TYPE == BACKEND_VULKAN #if BACKEND_TYPE == BACKEND_VULKAN
struct EGLInternalConfig { struct EGLInternalConfig {
@@ -69,9 +67,9 @@ extern std::atomic<uintptr_t> g_nextSurfaceId;
extern EGLenum g_currentAPI; extern EGLenum g_currentAPI;
extern std::mutex g_globalMutex; extern std::mutex g_globalMutex;
extern ankerl::unordered_map<EGLDisplay, VulkanDisplay> g_displays; extern MG_Global::unordered_map<EGLDisplay, VulkanDisplay> g_displays;
extern ankerl::unordered_map<EGLSurface, VulkanSurface> g_surfaces; extern MG_Global::unordered_map<EGLSurface, VulkanSurface> g_surfaces;
extern ankerl::unordered_map<EGLContext, VulkanContext> g_contexts; extern MG_Global::unordered_map<EGLContext, VulkanContext> g_contexts;
extern EGLint g_lastError; extern EGLint g_lastError;
extern thread_local EGLContext tls_currentContext; extern thread_local EGLContext tls_currentContext;
@@ -2,9 +2,18 @@
// Created by BZLZHH on 2025/3/15. // Created by BZLZHH on 2025/3/15.
// //
#include "GL_Buffer.h" #include "../../../../Includes.h"
namespace MG_GL::GL { namespace MG_GL::GL {
Diligent::VALUE_TYPE ConvertGLIndexTypeToDiligent(GLenum type) {
switch (type) {
case GL_UNSIGNED_BYTE: return Diligent::VT_UINT8;
case GL_UNSIGNED_SHORT: return Diligent::VT_UINT16;
case GL_UNSIGNED_INT: return Diligent::VT_UINT32;
default: return Diligent::VT_UNDEFINED;
}
}
void* MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, void* MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
GLbitfield access) { GLbitfield access) {
MG_Util::Debug::LogD("glMapBufferRange, target: %s, offset: %lld, length: %lld, access: 0x%X", MG_Util::Debug::LogD("glMapBufferRange, target: %s, offset: %lld, length: %lld, access: 0x%X",
@@ -31,6 +40,38 @@ namespace MG_GL::GL {
static_cast<long long>(length)); static_cast<long long>(length));
GLenum result = MG_State::SyncBufferMemory(target, offset, length); GLenum result = MG_State::SyncBufferMemory(target, offset, length);
if (result == GL_NO_ERROR) { if (result == GL_NO_ERROR) {
GLuint buffer = MG_State_T::bufferState->GetCurrentBinding(target);
if (buffer == 0) return;
auto& bufferObj = *MG_State_T::bufferState->GetBufferObject(buffer);
if (!bufferObj.isMapped) return;
size_t start = static_cast<size_t>(offset);
size_t end = start + static_cast<size_t>(length);
auto it = MG_Diligent::g_BufferMap.find(buffer);
if (it == MG_Diligent::g_BufferMap.end())
return;
Diligent::IBuffer* pBuffer = it->second;
if (pBuffer && bufferObj.data.size() >= end) {
const auto& Desc = pBuffer->GetDesc();
if (Desc.Usage == Diligent::USAGE_STAGING || Desc.Usage == Diligent::USAGE_DYNAMIC || Desc.Usage == Diligent::USAGE_UNIFIED) {
void * data;
MG_Diligent::g_pContext->MapBuffer(pBuffer, Diligent::MAP_WRITE,
Diligent::MAP_FLAG_DISCARD, data);
if (data) {
void* dst = static_cast<char*>(data) + offset;
const void* src = bufferObj.data.data() + offset;
memcpy(dst, src, length);
MG_Diligent::g_pContext->UnmapBuffer(pBuffer, Diligent::MAP_WRITE);
}
} else {
// For USAGE_DEFAULT or USAGE_IMMUTABLE, use UpdateBuffer
MG_Diligent::g_pContext->UpdateBuffer(pBuffer, static_cast<Diligent::Uint64>(offset), static_cast<Diligent::Uint64>(length), bufferObj.data.data() + offset, Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
}
}
return; return;
} }
MG_State::SetError(result); MG_State::SetError(result);
@@ -50,6 +91,25 @@ namespace MG_GL::GL {
static_cast<long long>(size)); static_cast<long long>(size));
GLenum result = MG_State::CopyBufferRange(readTarget, writeTarget, readOffset, writeOffset, size); GLenum result = MG_State::CopyBufferRange(readTarget, writeTarget, readOffset, writeOffset, size);
if (result == GL_NO_ERROR) { if (result == GL_NO_ERROR) {
GLuint srcBuffer = MG_State_T::bufferState->GetCurrentBinding(readTarget);
GLuint dstBuffer = MG_State_T::bufferState->GetCurrentBinding(writeTarget);
if (srcBuffer == 0 || dstBuffer == 0) return;
auto itsrc = MG_Diligent::g_BufferMap.find(srcBuffer);
auto itdst = MG_Diligent::g_BufferMap.find(dstBuffer);
if (itsrc == MG_Diligent::g_BufferMap.end() || itdst == MG_Diligent::g_BufferMap.end()) return;
Diligent::IBuffer* pSrcBuffer = itsrc->second;
Diligent::IBuffer* pDstBuffer = itdst->second;
if (pSrcBuffer && pDstBuffer) {
MG_Diligent::g_pContext->CopyBuffer(pSrcBuffer, static_cast<Diligent::Uint64>(readOffset),
Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION,
pDstBuffer, static_cast<Diligent::Uint64>(writeOffset),
static_cast<Diligent::Uint64>(size),
Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
}
return; return;
} }
MG_State::SetError(result); MG_State::SetError(result);
@@ -78,6 +138,31 @@ namespace MG_GL::GL {
MG_Util::Debug::LogE("glUnmapBuffer failed: %s", MG_Util::Debug::GLEnumToString(err)); MG_Util::Debug::LogE("glUnmapBuffer failed: %s", MG_Util::Debug::GLEnumToString(err));
return GL_FALSE; return GL_FALSE;
} }
GLuint buffer = MG_State_T::bufferState->currentBindings_[target];
auto& bufferObj = *MG_State_T::bufferState->GetBufferObject(buffer);
auto it = MG_Diligent::g_BufferMap.find(buffer);
if (it == MG_Diligent::g_BufferMap.end())
return GL_FALSE;
Diligent::IBuffer* pBuffer = it->second;
if (pBuffer) {
const auto& Desc = pBuffer->GetDesc();
if (Desc.Usage == Diligent::USAGE_STAGING || Desc.Usage == Diligent::USAGE_DYNAMIC || Desc.Usage == Diligent::USAGE_UNIFIED) {
void * data;
MG_Diligent::g_pContext->MapBuffer(pBuffer, Diligent::MAP_WRITE,
Diligent::MAP_FLAG_DISCARD, data);
if (data) {
memcpy(data, bufferObj.data.data(), bufferObj.data.size());
MG_Diligent::g_pContext->UnmapBuffer(pBuffer, Diligent::MAP_WRITE);
}
} else {
// For USAGE_DEFAULT or USAGE_IMMUTABLE, use UpdateBuffer
MG_Diligent::g_pContext->UpdateBuffer(pBuffer, 0, bufferObj.data.size(), bufferObj.data.data(), Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
}
}
MG_Util::Debug::LogD("glUnmapBuffer succeeded"); MG_Util::Debug::LogD("glUnmapBuffer succeeded");
return GL_TRUE; return GL_TRUE;
} }
@@ -112,8 +197,69 @@ namespace MG_GL::GL {
MG_Util::Debug::LogD("glBufferData, target: %s, size: %zd, data: %p, usage: %s", MG_Util::Debug::LogD("glBufferData, target: %s, size: %zd, data: %p, usage: %s",
MG_Util::Debug::GLEnumToString(target), size, data, MG_Util::Debug::GLEnumToString(usage)); MG_Util::Debug::GLEnumToString(target), size, data, MG_Util::Debug::GLEnumToString(usage));
GLenum result = MG_State::CommitBufferStorage(target, size, data, usage); GLenum result = MG_State::CommitBufferStorage(target, size, data, usage);
if (result == GL_NO_ERROR) if (result == GL_NO_ERROR) {
GLuint buffer = MG_State_T::bufferState->GetCurrentBinding(target);
if (buffer == 0) return;
auto& bufferObj = *MG_State_T::bufferState->GetBufferObject(buffer);
if (bufferObj.isDynamic) return; // Dynamic buffer should be created by glDraw*
if (size <= 0) return; // ignore 0-sized reallocation
bufferObj.dirty = false;
auto it = MG_Diligent::g_BufferMap.find(buffer);
if (it == MG_Diligent::g_BufferMap.end())
return;
Diligent::IBuffer*& pBuffer = it->second;
Diligent::BufferDesc BuffDesc;
std::string name;
BuffDesc.Size = static_cast<Diligent::Uint64>(size);
switch (target) {
case GL_ARRAY_BUFFER:
// BuffDesc.BindFlags = Diligent::BIND_VERTEX_BUFFER;
name += std::format("VBO {}", buffer);
break;
case GL_ELEMENT_ARRAY_BUFFER:
// BuffDesc.BindFlags = Diligent::BIND_INDEX_BUFFER;
name += std::format("IBO {}", buffer);
break;
case GL_UNIFORM_BUFFER:
// BuffDesc.BindFlags = Diligent::BIND_UNIFORM_BUFFER;
name += std::format("UBO {}", buffer);
break;
default:
BuffDesc.BindFlags = Diligent::BIND_SHADER_RESOURCE;
name += std::format("SRV {}", buffer);
break;
}
BuffDesc.BindFlags |= Diligent::BIND_VERTEX_BUFFER |
Diligent::BIND_INDEX_BUFFER |
Diligent::BIND_UNIFORM_BUFFER;
BuffDesc.Name = name.c_str();
BuffDesc.Usage = Diligent::USAGE_DEFAULT;
if (!pBuffer || (pBuffer && pBuffer->GetDesc().Size != bufferObj.data.size()) ) {
if (pBuffer) {
pBuffer->Release();
pBuffer = nullptr;
}
Diligent::BufferData BuffData;
// Initial data must not be null for immutable buffers
BuffData.pData = BuffDesc.Usage != Diligent::USAGE_IMMUTABLE ? nullptr : bufferObj.data.data();
BuffData.DataSize = static_cast<Diligent::Uint64>(size);
MG_Diligent::g_pDevice->CreateBuffer(BuffDesc, &BuffData, &pBuffer);
}
if (data != nullptr && BuffDesc.Usage != Diligent::USAGE_IMMUTABLE) {
MG_Diligent::g_pContext->UpdateBuffer(pBuffer, 0,
static_cast<Diligent::Uint64>(size), data,
Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
}
return; return;
}
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
} }
@@ -140,8 +286,9 @@ namespace MG_GL::GL {
GLenum result = MG_State::GenBufferNames(n, buffers); GLenum result = MG_State::GenBufferNames(n, buffers);
if (result == GL_NO_ERROR) { if (result == GL_NO_ERROR) {
MG_Util::Debug::LogD("Generated buffer names:"); MG_Util::Debug::LogD("Generated buffer names:");
for (GLsizei i = 0; i < n; ++i) { for (GLsizei i = 0; i < n; ++i) {
MG_Util::Debug::LogD(" Buffer[%d] = %u", i, buffers[i]); MG_Util::Debug::LogD(" Buffer[%d] = %u", i, buffers[i]);
MG_Diligent::g_BufferMap[buffers[i]] = nullptr;
} }
return; return;
} }
@@ -174,13 +321,57 @@ namespace MG_GL::GL {
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
} }
GLuint buffer = MG_State_T::bufferState->GetCurrentBinding(target);
if (buffer == 0) return;
auto& bufferObj = *MG_State_T::bufferState->GetBufferObject(buffer);
if (bufferObj.isDynamic) return; // Dynamic buffer should be created by glDraw*
auto it = MG_Diligent::g_BufferMap.find(buffer);
if (it == MG_Diligent::g_BufferMap.end())
return;
Diligent::IBuffer* pBuffer = it->second;
if (pBuffer) {
const auto& Desc = pBuffer->GetDesc();
if (Desc.Usage == Diligent::USAGE_STAGING || Desc.Usage == Diligent::USAGE_DYNAMIC || Desc.Usage == Diligent::USAGE_UNIFIED) {
void* pMappedData = nullptr;
MG_Diligent::g_pContext->MapBuffer(pBuffer, Diligent::MAP_WRITE, Diligent::MAP_FLAG_DISCARD, pMappedData);
if (pMappedData)
{
memcpy(static_cast<Diligent::Uint8*>(pMappedData) + offset, data, size);
MG_Diligent::g_pContext->UnmapBuffer(pBuffer, Diligent::MAP_WRITE);
} else {
MG_Util::Debug::LogE("Failed to map buffer for BufferSubData");
}
} else {
// For USAGE_DEFAULT or USAGE_IMMUTABLE, use UpdateBuffer
MG_Diligent::g_pContext->UpdateBuffer(pBuffer, static_cast<Diligent::Uint64>(offset),
static_cast<Diligent::Uint64>(size), data,
Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
}
}
} }
void DeleteBuffers(GLsizei n, const GLuint *buffers) { void DeleteBuffers(GLsizei n, const GLuint *buffers) {
MG_Util::Debug::LogD("glDeleteBuffers, n: %d, buffers: %p", n, buffers); MG_Util::Debug::LogD("glDeleteBuffers, n: %d, buffers: %p", n, buffers);
GLenum result = MG_State::DeleteBuffers(n, buffers); GLenum result = MG_State::DeleteBuffers(n, buffers);
if (result == GL_NO_ERROR) if (result == GL_NO_ERROR) {
for (GLsizei i = 0; i < n; ++i) {
GLuint buffer = buffers[i];
if (buffer != 0) {
auto it = MG_Diligent::g_BufferMap.find(buffer);
if (it != MG_Diligent::g_BufferMap.end()) {
if (it->second) {
it->second->Release();
}
MG_Diligent::g_BufferMap.erase(it);
}
}
}
return; return;
}
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
@@ -5,8 +5,6 @@
#ifndef MOBILEGL_GL_BUFFER_H #ifndef MOBILEGL_GL_BUFFER_H
#define MOBILEGL_GL_BUFFER_H #define MOBILEGL_GL_BUFFER_H
#include "../../../../Includes.h"
namespace MG_GL::GL { namespace MG_GL::GL {
void* MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); void* MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
void FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length); void FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length);
+124 -19
View File
@@ -2,23 +2,100 @@
// Created by BZLZHH on 2025/3/15. // Created by BZLZHH on 2025/3/15.
// //
#include "GL_Common.h" #include "../../../../Includes.h"
namespace MG_GL::GL { namespace MG_GL::GL {
void CreateRenderPassAndFramebuffer(GLuint framebuffer,
const FramebufferObject& fbo,
MG_Diligent::GLFramebufferInfo& fbInfo);
void Clear(GLbitfield mask) { void Clear(GLbitfield mask) {
MG_Util::Debug::LogD("glClear, mask: 0x%X", mask); GLuint drawFramebuffer = MG_State_T::framebufferState->currentBindings_[GL_DRAW_FRAMEBUFFER];
GLenum result = MG_State::glClear(mask); if (drawFramebuffer == 0) {
if (result == GL_NO_ERROR) { drawFramebuffer = 0;
}
auto it = MG_Diligent::g_FramebufferMap.find(drawFramebuffer);
if (it == MG_Diligent::g_FramebufferMap.end()) {
MG_Util::Debug::LogE("Framebuffer not found: %u", drawFramebuffer);
return; return;
} }
MG_State::SetError(result);
MG_Util::Debug::LogE("Error clearing buffers: %s", MG_Util::Debug::GLEnumToString(result)); MG_Diligent::GLFramebufferInfo& fbInfo = it->second;
auto& commonState = *MG_State_T::commonState;
MG_Util::Debug::LogD("Setting render targets: %zu color attachments", fbInfo.ColorRTVs.size());
MG_Diligent::g_pContext->SetRenderTargets(
static_cast<Diligent::Uint32>(fbInfo.ColorRTVs.size()),
fbInfo.ColorRTVs.data(),
fbInfo.pDepthStencilRTV,
::Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION
);
// if (MG_Diligent::IsInRenderPass) {
// MG_Util::Debug::LogD("Ending render pass before clear operation");
// MG_Diligent::g_pContext->EndRenderPass();
// MG_Diligent::IsInRenderPass = false;
// }
// MG_Util::Debug::LogD("Beginning render pass for clear operation");
// if (!fbInfo.pRenderPass) {
// MG_GL::GL::CreateRenderPassAndFramebuffer(drawFramebuffer,
// *MG_State_T::framebufferState->GetCurrentFBO(GL_DRAW_FRAMEBUFFER), fbInfo);
// }
// Diligent::BeginRenderPassAttribs beginAttribs;
// beginAttribs.pRenderPass = fbInfo.pRenderPass;
// beginAttribs.pFramebuffer = fbInfo.pFramebuffer;
// beginAttribs.StateTransitionMode = Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION;
// beginAttribs.ClearValueCount = 0;
// beginAttribs.pClearValues = nullptr;
// MG_Diligent::g_pContext->BeginRenderPass(beginAttribs);
// MG_Diligent::IsInRenderPass = true;
if (mask & GL_COLOR_BUFFER_BIT) {
for (size_t i = 0; i < fbInfo.ColorRTVs.size(); ++i) {
if (fbInfo.ColorRTVs[i]) {
MG_Util::Debug::LogD("Clearing color attachment %zu", i);
MG_Diligent::g_pContext->ClearRenderTarget(
fbInfo.ColorRTVs[i],
commonState.clearColor,
Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION
);
}
}
}
if (mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) {
if (fbInfo.pDepthStencilRTV) {
Diligent::Uint32 clearFlags = 0;
if (mask & GL_DEPTH_BUFFER_BIT) clearFlags |= Diligent::CLEAR_DEPTH_FLAG;
if (mask & GL_STENCIL_BUFFER_BIT) clearFlags |= Diligent::CLEAR_STENCIL_FLAG;
MG_Util::Debug::LogD("Clearing depth/stencil (flags: %u)", clearFlags);
MG_Diligent::g_pContext->ClearDepthStencil(
fbInfo.pDepthStencilRTV,
static_cast<Diligent::CLEAR_DEPTH_STENCIL_FLAGS>(clearFlags),
commonState.clearDepth,
0,
Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION
);
}
}
// MG_Util::Debug::LogD("Ending render pass after clear operation");
// MG_Diligent::g_pContext->EndRenderPass();
// MG_Diligent::IsInRenderPass = false;
} }
void Enable(GLenum cap) { void Enable(GLenum cap) {
MG_Util::Debug::LogD("glEnable, cap: %s", MG_Util::Debug::GLEnumToString(cap)); MG_Util::Debug::LogD("glEnable, cap: %s", MG_Util::Debug::GLEnumToString(cap));
GLenum result = MG_State::glEnable(cap); GLenum result = MG_State::glEnable(cap);
if (result == GL_NO_ERROR) return; if (result == GL_NO_ERROR) {
MG_Diligent::g_PSOManager.MarkPSODirty(MG_State_T::programState->currentProgram_);
return;
}
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Error enabling capability: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogE("Error enabling capability: %s", MG_Util::Debug::GLEnumToString(result));
} }
@@ -26,7 +103,10 @@ namespace MG_GL::GL {
void Disable(GLenum cap) { void Disable(GLenum cap) {
MG_Util::Debug::LogD("glDisable, cap: %s", MG_Util::Debug::GLEnumToString(cap)); MG_Util::Debug::LogD("glDisable, cap: %s", MG_Util::Debug::GLEnumToString(cap));
GLenum result = MG_State::glDisable(cap); GLenum result = MG_State::glDisable(cap);
if (result == GL_NO_ERROR) return; if (result == GL_NO_ERROR) {
MG_Diligent::g_PSOManager.MarkPSODirty(MG_State_T::programState->currentProgram_);
return;
}
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Error disabling capability: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogE("Error disabling capability: %s", MG_Util::Debug::GLEnumToString(result));
} }
@@ -36,7 +116,10 @@ namespace MG_GL::GL {
MG_Util::Debug::GLEnumToString(sfactor), MG_Util::Debug::GLEnumToString(sfactor),
MG_Util::Debug::GLEnumToString(dfactor)); MG_Util::Debug::GLEnumToString(dfactor));
GLenum result = MG_State::glBlendFunc(sfactor, dfactor); GLenum result = MG_State::glBlendFunc(sfactor, dfactor);
if (result == GL_NO_ERROR) return; if (result == GL_NO_ERROR) {
MG_Diligent::g_PSOManager.MarkPSODirty(MG_State_T::programState->currentProgram_);
return;
}
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Error setting blend func: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogE("Error setting blend func: %s", MG_Util::Debug::GLEnumToString(result));
} }
@@ -48,7 +131,10 @@ namespace MG_GL::GL {
MG_Util::Debug::GLEnumToString(srcAlpha), MG_Util::Debug::GLEnumToString(srcAlpha),
MG_Util::Debug::GLEnumToString(dstAlpha)); MG_Util::Debug::GLEnumToString(dstAlpha));
GLenum result = MG_State::glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); GLenum result = MG_State::glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
if (result == GL_NO_ERROR) return; if (result == GL_NO_ERROR) {
MG_Diligent::g_PSOManager.MarkPSODirty(MG_State_T::programState->currentProgram_);
return;
}
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Error setting separate blend func: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogE("Error setting separate blend func: %s", MG_Util::Debug::GLEnumToString(result));
} }
@@ -56,7 +142,10 @@ namespace MG_GL::GL {
void ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { void ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
MG_Util::Debug::LogD("glClearColor, rgba: [%.2f, %.2f, %.2f, %.2f]", red, green, blue, alpha); MG_Util::Debug::LogD("glClearColor, rgba: [%.2f, %.2f, %.2f, %.2f]", red, green, blue, alpha);
GLenum result = MG_State::glClearColor(red, green, blue, alpha); GLenum result = MG_State::glClearColor(red, green, blue, alpha);
if (result == GL_NO_ERROR) return; if (result == GL_NO_ERROR) {
MG_Diligent::g_PSOManager.MarkPSODirty(MG_State_T::programState->currentProgram_);
return;
}
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Error setting clear color: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogE("Error setting clear color: %s", MG_Util::Debug::GLEnumToString(result));
} }
@@ -64,7 +153,10 @@ namespace MG_GL::GL {
void ClearDepth(GLdouble depth) { void ClearDepth(GLdouble depth) {
MG_Util::Debug::LogD("glClearDepth, depth: %.3f", depth); MG_Util::Debug::LogD("glClearDepth, depth: %.3f", depth);
GLenum result = MG_State::glClearDepth(depth); GLenum result = MG_State::glClearDepth(depth);
if (result == GL_NO_ERROR) return; if (result == GL_NO_ERROR) {
MG_Diligent::g_PSOManager.MarkPSODirty(MG_State_T::programState->currentProgram_);
return;
}
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Error setting clear depth: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogE("Error setting clear depth: %s", MG_Util::Debug::GLEnumToString(result));
} }
@@ -72,7 +164,10 @@ namespace MG_GL::GL {
void ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) { void ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
MG_Util::Debug::LogD("glColorMask, rgba: [%d, %d, %d, %d]", red, green, blue, alpha); MG_Util::Debug::LogD("glColorMask, rgba: [%d, %d, %d, %d]", red, green, blue, alpha);
GLenum result = MG_State::glColorMask(red, green, blue, alpha); GLenum result = MG_State::glColorMask(red, green, blue, alpha);
if (result == GL_NO_ERROR) return; if (result == GL_NO_ERROR) {
MG_Diligent::g_PSOManager.MarkPSODirty(MG_State_T::programState->currentProgram_);
return;
}
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Error setting color mask: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogE("Error setting color mask: %s", MG_Util::Debug::GLEnumToString(result));
} }
@@ -80,7 +175,10 @@ namespace MG_GL::GL {
void DepthFunc(GLenum func) { void DepthFunc(GLenum func) {
MG_Util::Debug::LogD("glDepthFunc, func: %s", MG_Util::Debug::GLEnumToString(func)); MG_Util::Debug::LogD("glDepthFunc, func: %s", MG_Util::Debug::GLEnumToString(func));
GLenum result = MG_State::glDepthFunc(func); GLenum result = MG_State::glDepthFunc(func);
if (result == GL_NO_ERROR) return; if (result == GL_NO_ERROR) {
MG_Diligent::g_PSOManager.MarkPSODirty(MG_State_T::programState->currentProgram_);
return;
}
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Error setting depth func: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogE("Error setting depth func: %s", MG_Util::Debug::GLEnumToString(result));
} }
@@ -88,7 +186,10 @@ namespace MG_GL::GL {
void DepthMask(GLboolean flag) { void DepthMask(GLboolean flag) {
MG_Util::Debug::LogD("glDepthMask, flag: %d", flag); MG_Util::Debug::LogD("glDepthMask, flag: %d", flag);
GLenum result = MG_State::glDepthMask(flag); GLenum result = MG_State::glDepthMask(flag);
if (result == GL_NO_ERROR) return; if (result == GL_NO_ERROR) {
MG_Diligent::g_PSOManager.MarkPSODirty(MG_State_T::programState->currentProgram_);
return;
}
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Error setting depth mask: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogE("Error setting depth mask: %s", MG_Util::Debug::GLEnumToString(result));
} }
@@ -97,16 +198,20 @@ namespace MG_GL::GL {
MG_Util::Debug::LogD("glViewport, x: %d, y: %d, width: %d, height: %d", MG_Util::Debug::LogD("glViewport, x: %d, y: %d, width: %d, height: %d",
x, y, width, height); x, y, width, height);
GLenum result = MG_State::glViewport(x, y, width, height); GLenum result = MG_State::glViewport(x, y, width, height);
if (result == GL_NO_ERROR) return; if (result == GL_NO_ERROR) {
return;
}
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Error setting viewport: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogE("Error setting viewport: %s", MG_Util::Debug::GLEnumToString(result));
} }
void PixelStorei(GLenum pname, GLint param) { void PixelStorei(GLenum pname, GLint param) {
MG_Util::Debug::LogD("glPixelStorei, pname: %d, param: %d", pname, param); MG_Util::Debug::LogD("glPixelStorei, pname: %s, param: %d", MG_Util::Debug::GLEnumToString(pname), param);
GLenum result = MG_State::SetPixelStoreInt(pname,param); GLenum result = MG_State::SetPixelStoreInt(pname,param);
if (result == GL_NO_ERROR) if (result == GL_NO_ERROR) {
MG_Diligent::g_PSOManager.MarkPSODirty(MG_State_T::programState->currentProgram_);
return; return;
}
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
} }
@@ -5,8 +5,6 @@
#ifndef MOBILEGL_GL_COMMON_H #ifndef MOBILEGL_GL_COMMON_H
#define MOBILEGL_GL_COMMON_H #define MOBILEGL_GL_COMMON_H
#include "../../../../Includes.h"
namespace MG_GL::GL { namespace MG_GL::GL {
void ClearDepth(GLdouble depth); void ClearDepth(GLdouble depth);
void ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); void ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
File diff suppressed because it is too large Load Diff
@@ -4,15 +4,17 @@
#ifndef MOBILEGL_GL_DRAWING_H #ifndef MOBILEGL_GL_DRAWING_H
#define MOBILEGL_GL_DRAWING_H #define MOBILEGL_GL_DRAWING_H
#include "../../../../Includes.h"
namespace MG_GL::GL { namespace MG_GL::GL {
bool IsSamplerType(GLenum type);
Diligent::VALUE_TYPE ConvertGLTypeToDiligent(GLenum type);
void PrepareForDraw(GLenum mode, GLsizei* pCount, GLenum& type, const void*& pIndices);
void DrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices); void DrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices);
void DrawArrays(GLenum mode, GLint first, GLsizei count); void DrawArrays(GLenum mode, GLint first, GLsizei count);
void DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex); void DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex);
void MultiDrawElements(GLenum mode, const GLsizei *count, GLenum type, const GLvoid *const *indices, GLsizei drawcount); void MultiDrawElements(GLenum mode, const GLsizei *count, GLenum type, const GLvoid *const *indices, GLsizei drawcount);
void MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count, GLenum type, const GLvoid *const *indices, GLsizei drawcount, const GLint *basevertex); void MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count, GLenum type, const GLvoid *const *indices, GLsizei drawcount, const GLint *basevertex);
void DrawBuffer(GLenum buf);
} }
#endif //MOBILEGL_GL_DRAWING_H #endif //MOBILEGL_GL_DRAWING_H
@@ -2,13 +2,235 @@
// Created by BZLZHH on 2025/3/15. // Created by BZLZHH on 2025/3/15.
// //
#include "GL_Framebuffer.h" #include "../../../../Includes.h"
namespace MG_GL::GL { namespace MG_GL::GL {
void ReleaseFramebufferResources(MG_Diligent::GLFramebufferInfo& fbInfo) {
// if (fbInfo.pFramebuffer) {
// fbInfo.pFramebuffer->Release();
// fbInfo.pFramebuffer = nullptr;
// }
// if (fbInfo.pRenderPass) {
// fbInfo.pRenderPass->Release();
// fbInfo.pRenderPass = nullptr;
// }
}
void CreateRenderPassAndFramebuffer(GLuint framebuffer,
const FramebufferObject& fbo,
MG_Diligent::GLFramebufferInfo& fbInfo) {
Diligent::Uint32 width = 0;
Diligent::Uint32 height = 0;
if (framebuffer == 0) {
if (MG_Diligent::g_pSwapChain) {
width = MG_Diligent::g_pSwapChain->GetDesc().Width;
height = MG_Diligent::g_pSwapChain->GetDesc().Height;
MG_Util::Debug::LogD("CreateRenderPassAndFramebuffer: Using swap chain dimensions: %ux%u", width, height);
} else {
MG_Util::Debug::LogE("CreateRenderPassAndFramebuffer: Swap chain not initialized for default framebuffer");
return;
}
} else if (!fbInfo.ColorRTVs.empty() && fbInfo.ColorRTVs[0]) {
const auto& desc = fbInfo.ColorRTVs[0]->GetTexture()->GetDesc();
width = desc.Width;
height = desc.Height;
MG_Util::Debug::LogD("CreateRenderPassAndFramebuffer: Using color attachment 0 for dimensions: %ux%u", width, height);
} else if (fbInfo.pDepthStencilRTV) {
const auto& desc = fbInfo.pDepthStencilRTV->GetTexture()->GetDesc();
width = desc.Width;
height = desc.Height;
MG_Util::Debug::LogD("CreateRenderPassAndFramebuffer: Using depth/stencil attachment for dimensions: %ux%u", width, height);
} else {
MG_Util::Debug::LogD("CreateRenderPassAndFramebuffer: Failed to determine framebuffer dimensions. No attachments.");
return;
}
if (width == 0 || height == 0) {
MG_Util::Debug::LogE("CreateRenderPassAndFramebuffer: Failed to determine framebuffer dimensions. Width or Height is 0.");
return;
}
// Diligent::RenderPassDesc RPDesc;
// std::vector<Diligent::RenderPassAttachmentDesc> Attachments;
// std::vector<Diligent::SubpassDesc> Subpasses;
// std::vector<Diligent::AttachmentReference> ColorRefs;
//
// for (size_t i = 0; i < fbInfo.ColorRTVs.size(); ++i) {
// if (fbInfo.ColorRTVs[i]) {
// Diligent::RenderPassAttachmentDesc ColorAttachment;
// ColorAttachment.Format = framebuffer != 0 ? fbInfo.ColorRTVs[i]->GetDesc().Format:
// MG_Diligent::g_pSwapChain->GetDesc().ColorBufferFormat;
// ColorAttachment.SampleCount = 1;
// ColorAttachment.InitialState = Diligent::RESOURCE_STATE_RENDER_TARGET;
// ColorAttachment.FinalState = Diligent::RESOURCE_STATE_RENDER_TARGET;
// ColorAttachment.LoadOp = Diligent::ATTACHMENT_LOAD_OP_LOAD;
// ColorAttachment.StoreOp = Diligent::ATTACHMENT_STORE_OP_STORE;
// Attachments.push_back(ColorAttachment);
//
// Diligent::AttachmentReference ColorRef;
// ColorRef.AttachmentIndex = static_cast<Diligent::Uint32>(Attachments.size() - 1);
// ColorRef.State = Diligent::RESOURCE_STATE_RENDER_TARGET;
// ColorRefs.push_back(ColorRef);
// MG_Util::Debug::LogD("CreateRenderPassAndFramebuffer: Added color attachment %zu", i);
// }
// }
// Diligent::AttachmentReference DepthRef;
// if (fbInfo.pDepthStencilRTV) {
// Diligent::RenderPassAttachmentDesc DepthAttachment;
// DepthAttachment.Format = fbInfo.DepthStencilFormat;
// DepthAttachment.SampleCount = 1;
// DepthAttachment.InitialState = Diligent::RESOURCE_STATE_DEPTH_WRITE;
// DepthAttachment.FinalState = Diligent::RESOURCE_STATE_DEPTH_WRITE;
// DepthAttachment.LoadOp = Diligent::ATTACHMENT_LOAD_OP_LOAD;
// DepthAttachment.StoreOp = Diligent::ATTACHMENT_STORE_OP_STORE;
// DepthAttachment.StencilLoadOp = Diligent::ATTACHMENT_LOAD_OP_LOAD;
// DepthAttachment.StencilStoreOp = Diligent::ATTACHMENT_STORE_OP_STORE;
// Attachments.push_back(DepthAttachment);
//
// DepthRef.AttachmentIndex = static_cast<Diligent::Uint32>(Attachments.size() - 1);
// DepthRef.State = Diligent::RESOURCE_STATE_DEPTH_WRITE;
// MG_Util::Debug::LogD("CreateRenderPassAndFramebuffer: Added depth/stencil attachment");
// }
// Diligent::SubpassDesc Subpass;
// Subpass.RenderTargetAttachmentCount = static_cast<Diligent::Uint32>(ColorRefs.size());
// Subpass.pRenderTargetAttachments = ColorRefs.empty() ? nullptr : ColorRefs.data();
// Subpass.pDepthStencilAttachment = fbInfo.pDepthStencilRTV ? &DepthRef : nullptr;
// Subpasses.push_back(Subpass);
//
// RPDesc.AttachmentCount = static_cast<Diligent::Uint32>(Attachments.size());
// RPDesc.pAttachments = Attachments.empty() ? nullptr : Attachments.data();
// RPDesc.SubpassCount = static_cast<Diligent::Uint32>(Subpasses.size());
// RPDesc.pSubpasses = Subpasses.data();
//
// MG_Util::Debug::LogD("CreateRenderPassAndFramebuffer: Creating RenderPass with %u attachments and %u subpasses.",
// RPDesc.AttachmentCount, RPDesc.SubpassCount);
//
// MG_Diligent::g_pDevice->CreateRenderPass(RPDesc, &fbInfo.pRenderPass);
// if (!fbInfo.pRenderPass) {
// MG_Util::Debug::LogE("CreateRenderPassAndFramebuffer: Failed to create RenderPass.");
// return;
// }
// MG_Util::Debug::LogD("CreateRenderPassAndFramebuffer: RenderPass created successfully.");
// Diligent::FramebufferDesc FBDesc;
// FBDesc.Name = "Framebuffer";
//// FBDesc.pRenderPass = fbInfo.pRenderPass;
// FBDesc.AttachmentCount = static_cast<Diligent::Uint32>(Attachments.size());
//
// std::vector<Diligent::ITextureView *> FBAtachments(Attachments.size());
// for (size_t i = 0; i < ColorRefs.size(); ++i) {
// if (i < fbInfo.ColorRTVs.size() && fbInfo.ColorRTVs[i]) {
// FBAtachments[i] = fbInfo.ColorRTVs[i];
// }
// }
//
// if (fbInfo.pDepthStencilRTV) {
// FBAtachments[ColorRefs.size()] = fbInfo.pDepthStencilRTV;
// }
// FBDesc.ppAttachments = FBAtachments.data();
// FBDesc.Width = width;
// FBDesc.Height = height;
// FBDesc.NumArraySlices = 1;
//
// MG_Util::Debug::LogD("CreateRenderPassAndFramebuffer: FramebufferDesc Details:");
// MG_Util::Debug::LogD(" Name: %s", FBDesc.Name ? FBDesc.Name : "N/A");
// MG_Util::Debug::LogD(" pRenderPass: %p", FBDesc.pRenderPass);
// MG_Util::Debug::LogD(" AttachmentCount: %u", FBDesc.AttachmentCount);
// for (Diligent::Uint32 i = 0; i < FBDesc.AttachmentCount; ++i) {
// if (FBDesc.ppAttachments && FBDesc.ppAttachments[i]) {
// Diligent::ITexture* pTexture = FBDesc.ppAttachments[i]->GetTexture();
// if (pTexture) {
// const auto& texDesc = pTexture->GetDesc();
// MG_Util::Debug::LogD(" Attachment %u: Texture '%s', Dim: %ux%u",
// i, texDesc.Name ? texDesc.Name : "N/A", texDesc.Width, texDesc.Height);
// } else {
// MG_Util::Debug::LogW(" Attachment %u: TextureView's texture is nullptr", i);
// }
// } else if (!FBDesc.ppAttachments) {
// MG_Util::Debug::LogW(" FBDesc.ppAttachments is nullptr. Cannot access attachment %u.", i);
// } else {
// MG_Util::Debug::LogD(" Attachment %u: nullptr", i);
// }
// }
// MG_Util::Debug::LogD(" Width: %u", FBDesc.Width);
// MG_Util::Debug::LogD(" Height: %u", FBDesc.Height);
// MG_Util::Debug::LogD(" NumArraySlices: %u", FBDesc.NumArraySlices);
// MG_Util::Debug::LogD(" fbInfo.pFramebuffer: %p", fbInfo.pFramebuffer);
fbInfo.ClearValues.clear();
for (size_t i = 0; i < fbInfo.ColorRTVs.size(); ++i) {
Diligent::OptimizedClearValue clearValue;
clearValue.Color[0] = 0.0f;
clearValue.Color[1] = 0.0f;
clearValue.Color[2] = 0.0f;
clearValue.Color[3] = 1.0f;
fbInfo.ClearValues.push_back(clearValue);
}
if (fbInfo.pDepthStencilRTV) {
Diligent::OptimizedClearValue clearValue;
clearValue.DepthStencil.Depth = 1.0f;
clearValue.DepthStencil.Stencil = 0;
fbInfo.ClearValues.push_back(clearValue);
}
// MG_Diligent::g_pDevice->CreateFramebuffer(FBDesc, &fbInfo.pFramebuffer);
// if (!fbInfo.pFramebuffer) {
// MG_Util::Debug::LogE("CreateRenderPassAndFramebuffer: Failed to create Framebuffer.");
// return;
// }
// MG_Util::Debug::LogD("CreateRenderPassAndFramebuffer: Framebuffer created successfully.");
}
void UpdateDefaultFramebuffer() {
auto it = MG_Diligent::g_FramebufferMap.find(0);
if (it == MG_Diligent::g_FramebufferMap.end()) {
MG_Diligent::g_FramebufferMap[0] = MG_Diligent::GLFramebufferInfo();
}
MG_Diligent::GLFramebufferInfo& fbInfo = MG_Diligent::g_FramebufferMap[0];
ReleaseFramebufferResources(fbInfo);
if (MG_Diligent::g_pSwapChain) {
Diligent::ITextureView* pRTV = MG_Diligent::g_pSwapChain->GetCurrentBackBufferRTV();
Diligent::ITextureView* pDSV = MG_Diligent::g_pSwapChain->GetDepthBufferDSV();
if (pRTV) {
fbInfo.ColorRTVs = { pRTV };
} else {
MG_Util::Debug::LogE("Failed to get swap chain back buffer RTV");
}
if (pDSV) {
fbInfo.pDepthStencilRTV = pDSV;
fbInfo.DepthStencilFormat = MG_Diligent::g_pSwapChain->GetDesc().DepthBufferFormat;
fbInfo.HasDepthStencil = true;
} else {
MG_Util::Debug::LogE("Failed to get swap chain depth buffer DSV");
}
CreateRenderPassAndFramebuffer(0, FramebufferObject(), fbInfo);
} else {
MG_Util::Debug::LogE("Swap chain not initialized for default framebuffer");
}
}
void GenFramebuffers(GLsizei n, GLuint* framebuffers) { void GenFramebuffers(GLsizei n, GLuint* framebuffers) {
MG_Util::Debug::LogD("glGenFramebuffers, n: %d, framebuffers: %p", n, framebuffers); MG_Util::Debug::LogD("glGenFramebuffers, n: %d, framebuffers: %p", n, framebuffers);
GLenum result = MG_State::CreateFramebuffers(n, framebuffers); GLenum result = MG_State::CreateFramebuffers(n, framebuffers);
if (result == GL_NO_ERROR) return; if (result == GL_NO_ERROR) {
for (GLsizei i = 0; i < n; ++i) {
MG_Diligent::GLFramebufferInfo fbInfo;
MG_Diligent::g_FramebufferMap[framebuffers[i]] = fbInfo;
}
return;
};
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Framebuffer generation failed: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogE("Framebuffer generation failed: %s", MG_Util::Debug::GLEnumToString(result));
} }
@@ -21,18 +243,205 @@ namespace MG_GL::GL {
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Failed to delete framebuffer %u: %s", MG_Util::Debug::LogE("Failed to delete framebuffer %u: %s",
framebuffers[i], MG_Util::Debug::GLEnumToString(result)); framebuffers[i], MG_Util::Debug::GLEnumToString(result));
} else {
GLuint fb = framebuffers[i];
auto it = MG_Diligent::g_FramebufferMap.find(fb);
if (it != MG_Diligent::g_FramebufferMap.end()) {
MG_Diligent::GLFramebufferInfo& fbInfo = it->second;
// if (fbInfo.pFramebuffer) {
// fbInfo.pFramebuffer->Release();
// }
// if (fbInfo.pRenderPass) {
// fbInfo.pRenderPass->Release();
// }
for (auto& rtv : fbInfo.ColorRTVs) {
if (rtv) rtv->Release();
}
if (fbInfo.pDepthStencilRTV) {
fbInfo.pDepthStencilRTV->Release();
}
MG_Diligent::g_FramebufferMap.erase(it);
}
} }
} }
} }
void BindFramebuffer(GLenum target, GLuint framebuffer) { void BindFramebuffer(GLenum target, GLuint framebuffer) {
MG_Util::Debug::LogD("glBindFramebuffer, target: %s, fb: %u", MG_Util::Debug::LogD("BindFramebuffer: Start. Target: %s, Framebuffer: %u",
MG_Util::Debug::GLEnumToString(target), framebuffer); MG_Util::Debug::GLEnumToString(target), framebuffer);
GLenum result = MG_State::BindFramebuffer(target, framebuffer); GLenum result = MG_State::BindFramebuffer(target, framebuffer);
if (result == GL_NO_ERROR) return; if (result == GL_NO_ERROR) {
MG_Util::Debug::LogD("BindFramebuffer: MG_State::BindFramebuffer successful.");
// if (MG_Diligent::IsInRenderPass) {
// MG_Util::Debug::LogD("BindFramebuffer: Ending current render pass.");
// MG_Diligent::g_pContext->EndRenderPass();
// MG_Diligent::IsInRenderPass = false;
// MG_Util::Debug::LogD("BindFramebuffer: Current render pass ended.");
// } else {
// MG_Util::Debug::LogD("BindFramebuffer: No active render pass to end.");
// }
if (framebuffer == 0) {
MG_Util::Debug::LogD("BindFramebuffer: Framebuffer is 0 (default framebuffer). Updating default framebuffer.");
UpdateDefaultFramebuffer();
MG_Util::Debug::LogD("BindFramebuffer: Default framebuffer updated.");
}
FramebufferObject* pFBO = MG_State_T::framebufferState->GetCurrentFBO(target);
MG_Util::Debug::LogD("BindFramebuffer: Retrieved FBO from state: %p", pFBO);
auto it = MG_Diligent::g_FramebufferMap.find(framebuffer);
if (it == MG_Diligent::g_FramebufferMap.end()) {
MG_Util::Debug::LogE("BindFramebuffer: Framebuffer %u not found in g_FramebufferMap. Aborting.", framebuffer);
return;
}
MG_Util::Debug::LogD("BindFramebuffer: Framebuffer %u found in g_FramebufferMap.", framebuffer);
MG_Diligent::GLFramebufferInfo& fbInfo = it->second;
// if (/*!fbInfo.pRenderPass || */!fbInfo.pFramebuffer) {
// MG_Util::Debug::LogD("BindFramebuffer: RenderPass or Framebuffer not yet created for framebuffer %u. Creating now.", framebuffer);
// CreateRenderPassAndFramebuffer(framebuffer, pFBO ? *pFBO : FramebufferObject(), fbInfo);
// MG_Util::Debug::LogD("BindFramebuffer: RenderPass and Framebuffer creation attempted for framebuffer %u.", framebuffer);
// } else {
// MG_Util::Debug::LogD("BindFramebuffer: RenderPass and Framebuffer already exist for framebuffer %u.", framebuffer);
// }
MG_Util::Debug::LogD("BindFramebuffer: Setting render targets. ColorRTVs count: %zu, DepthStencilRTV: %p",
fbInfo.ColorRTVs.size(), fbInfo.pDepthStencilRTV);
MG_Diligent::g_pContext->SetRenderTargets(
static_cast<Diligent::Uint32>(fbInfo.ColorRTVs.size()),
fbInfo.ColorRTVs.empty() ? nullptr : fbInfo.ColorRTVs.data(),
fbInfo.pDepthStencilRTV,
Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION
);
MG_Util::Debug::LogD("BindFramebuffer: SetRenderTargets called.");
return;
}
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Framebuffer bind error: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogE("Framebuffer bind error: %s", MG_Util::Debug::GLEnumToString(result));
} }
void AttachTexture2DToFramebuffer(GLuint fbo, GLuint texture, GLenum attachment, GLint level) {
auto it = MG_Diligent::g_FramebufferMap.find(fbo);
if (it == MG_Diligent::g_FramebufferMap.end()) {
MG_Util::Debug::LogE("Framebuffer %u not found in map", fbo);
return;
}
MG_Diligent::GLFramebufferInfo& fbInfo = it->second;
// if (fbInfo.pFramebuffer) {
// fbInfo.pFramebuffer->Release();
// fbInfo.pFramebuffer = nullptr;
// MG_Util::Debug::LogD("Released existing framebuffer");
// }
// if (fbInfo.pRenderPass) {
// fbInfo.pRenderPass->Release();
// fbInfo.pRenderPass = nullptr;
// MG_Util::Debug::LogD("Released existing render pass");
// }
if (texture == 0) {
MG_Util::Debug::LogD("Unbinding attachment: %s", MG_Util::Debug::GLEnumToString(attachment));
if (attachment == GL_DEPTH_ATTACHMENT ||
attachment == GL_STENCIL_ATTACHMENT ||
attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
if (fbInfo.pDepthStencilRTV) {
fbInfo.pDepthStencilRTV->Release();
fbInfo.pDepthStencilRTV = nullptr;
MG_Util::Debug::LogD("Released depth/stencil attachment");
}
} else {
size_t index = attachment - GL_COLOR_ATTACHMENT0;
if (index < fbInfo.ColorRTVs.size() && fbInfo.ColorRTVs[index]) {
fbInfo.ColorRTVs[index]->Release();
fbInfo.ColorRTVs[index] = nullptr;
bool allNull = true;
for (const auto& rtv : fbInfo.ColorRTVs) {
if (rtv != nullptr) {
allNull = false;
break;
}
}
if (allNull) fbInfo.ColorRTVs.clear();
MG_Util::Debug::LogD("Released color attachment %zu", index);
}
}
} else {
Diligent::ITexture* pTexture = MG_Diligent::g_TextureMap[texture];
if (!pTexture) {
MG_Util::Debug::LogE("Texture %u exists in map but pointer is null", texture);
return;
}
const auto& texDesc = pTexture->GetDesc();
MG_Util::Debug::LogD("Attaching texture: %s (size: %ux%u)",
texDesc.Name,
texDesc.Width, texDesc.Height);
Diligent::TextureViewDesc ViewDesc;
ViewDesc.TextureDim = Diligent::RESOURCE_DIM_TEX_2D;
ViewDesc.MostDetailedMip = level;
ViewDesc.NumMipLevels = 1;
if (attachment == GL_DEPTH_ATTACHMENT ||
attachment == GL_STENCIL_ATTACHMENT ||
attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
MG_Util::Debug::LogD("Creating depth/stencil attachment");
if (fbInfo.pDepthStencilRTV) {
fbInfo.pDepthStencilRTV->Release();
fbInfo.pDepthStencilRTV = nullptr;
MG_Util::Debug::LogD("Released existing depth/stencil attachment");
}
ViewDesc.ViewType = Diligent::TEXTURE_VIEW_DEPTH_STENCIL;
fbInfo.DepthStencilFormat = texDesc.Format;
pTexture->CreateView(ViewDesc, &fbInfo.pDepthStencilRTV);
if (fbInfo.pDepthStencilRTV) {
fbInfo.HasDepthStencil = true;
MG_Util::Debug::LogD("Created new depth/stencil RTV");
} else {
MG_Util::Debug::LogE("Failed to create depth/stencil RTV");
}
} else {
size_t index = attachment - GL_COLOR_ATTACHMENT0;
MG_Util::Debug::LogD("Creating color attachment at index %zu", index);
if (index >= fbInfo.ColorRTVs.size()) {
fbInfo.ColorRTVs.resize(index + 1, nullptr);
MG_Util::Debug::LogD("Resized color attachments to %zu", fbInfo.ColorRTVs.size());
}
if (fbInfo.ColorRTVs[index]) {
fbInfo.ColorRTVs[index]->Release();
fbInfo.ColorRTVs[index] = nullptr;
MG_Util::Debug::LogD("Released existing color attachment %zu", index);
}
ViewDesc.ViewType = Diligent::TEXTURE_VIEW_RENDER_TARGET;
pTexture->CreateView(ViewDesc, &fbInfo.ColorRTVs[index]);
if (fbInfo.ColorRTVs[index]) {
MG_Util::Debug::LogD("Created new color RTV at index %zu", index);
} else {
MG_Util::Debug::LogE("Failed to create color RTV at index %zu", index);
}
}
}
}
void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget,
GLuint texture, GLint level) { GLuint texture, GLint level) {
@@ -40,13 +449,52 @@ namespace MG_GL::GL {
MG_Util::Debug::GLEnumToString(target), MG_Util::Debug::GLEnumToString(target),
MG_Util::Debug::GLEnumToString(attachment), MG_Util::Debug::GLEnumToString(attachment),
MG_Util::Debug::GLEnumToString(textarget), MG_Util::Debug::GLEnumToString(textarget),
texture, level); texture,
level);
if (target == GL_FRAMEBUFFER) {
MG_Util::Debug::LogD("Got target == GL_FRAMEBUFFER, treating as GL_DRAW_FRAMEBUFFER");
target = GL_DRAW_FRAMEBUFFER;
}
MG_Util::Debug::LogD(" Current READ_FRAMEBUFFER binding: %u", MG_State_T::framebufferState->currentBindings_[GL_READ_FRAMEBUFFER]);
MG_Util::Debug::LogD(" Current DRAW_FRAMEBUFFER binding: %u", MG_State_T::framebufferState->currentBindings_[GL_DRAW_FRAMEBUFFER]);
GLenum result = MG_State::AttachTexture2DToFramebuffer( GLenum result = MG_State::AttachTexture2DToFramebuffer(
target, attachment, textarget, texture, level target, attachment, textarget, texture, level
); );
if (result == GL_NO_ERROR) return; if (result == GL_NO_ERROR) {
// if (target == GL_FRAMEBUFFER) {
// if (MG_State_T::framebufferState->currentBindings_[GL_READ_FRAMEBUFFER] == MG_State_T::framebufferState->currentBindings_[GL_DRAW_FRAMEBUFFER]) {
// MG_Util::Debug::LogD(" Target is GL_FRAMEBUFFER and READ/DRAW bindings are the same (%u). Applying to GL_DRAW_FRAMEBUFFER.",
// MG_State_T::framebufferState->currentBindings_[GL_DRAW_FRAMEBUFFER]);
// target = GL_DRAW_FRAMEBUFFER;
// } else {
// MG_Util::Debug::LogD(" Target is GL_FRAMEBUFFER and READ/DRAW bindings differ. Applying to both if non-zero.");
// if (MG_State_T::framebufferState->currentBindings_[GL_READ_FRAMEBUFFER] != 0) {
// MG_Util::Debug::LogD(" Attaching to READ_FRAMEBUFFER: %u", MG_State_T::framebufferState->currentBindings_[GL_READ_FRAMEBUFFER]);
// AttachTexture2DToFramebuffer(MG_State_T::framebufferState->currentBindings_[GL_READ_FRAMEBUFFER],
// texture, attachment, level);
// }
// if (MG_State_T::framebufferState->currentBindings_[GL_DRAW_FRAMEBUFFER] != 0) {
// MG_Util::Debug::LogD(" Attaching to DRAW_FRAMEBUFFER: %u", MG_State_T::framebufferState->currentBindings_[GL_DRAW_FRAMEBUFFER]);
// AttachTexture2DToFramebuffer(MG_State_T::framebufferState->currentBindings_[GL_DRAW_FRAMEBUFFER],
// texture, attachment, level);
// }
// MG_Util::Debug::LogD("FramebufferTexture2D completed successfully after separate READ/DRAW attachments.");
// return;
// }
// }
GLuint fboToModify = MG_State_T::framebufferState->currentBindings_[target];
MG_Util::Debug::LogD(" Target is %s. Applying to bound FBO: %u",
MG_Util::Debug::GLEnumToString(target), fboToModify);
AttachTexture2DToFramebuffer(fboToModify,
texture, attachment, level);
MG_Util::Debug::LogD("FramebufferTexture2D completed successfully for target %s (FBO %u).", MG_Util::Debug::GLEnumToString(target), fboToModify);
return;
}
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Texture attachment failed: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogE("Texture attachment failed: %s", MG_Util::Debug::GLEnumToString(result));
} }
@@ -56,8 +504,7 @@ namespace MG_GL::GL {
MG_Util::Debug::GLEnumToString(target)); MG_Util::Debug::GLEnumToString(target));
GLenum result = MG_State::ValidateFramebufferCompleteness(target); GLenum result = MG_State::ValidateFramebufferCompleteness(target);
if (result >= GL_FRAMEBUFFER_COMPLETE) { if (result >= GL_FRAMEBUFFER_COMPLETE) {
MG_Util::Debug::LogD("Framebuffer status: %s", MG_Util::Debug::LogD("Framebuffer status: %s", MG_Util::Debug::GLEnumToString(result));
MG_Util::Debug::GLEnumToString(result));
return result; return result;
} }
MG_State::SetError(result); MG_State::SetError(result);
@@ -68,6 +515,92 @@ namespace MG_GL::GL {
void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
// TODO // if (MG_Diligent::IsInRenderPass) {
// MG_Util::Debug::LogD("Ending current render pass.");
// MG_Diligent::g_pContext->EndRenderPass();
// MG_Diligent::IsInRenderPass = false;
// MG_Util::Debug::LogD("Current render pass ended.");
// }
// explicitly unbind the texture
MG_Diligent::g_pContext->SetRenderTargets(0, nullptr, nullptr, Diligent::RESOURCE_STATE_TRANSITION_MODE_NONE);
GLuint readFB = MG_State_T::framebufferState->currentBindings_[GL_READ_FRAMEBUFFER];
GLuint drawFB = MG_State_T::framebufferState->currentBindings_[GL_DRAW_FRAMEBUFFER];
MG_Diligent::GLFramebufferInfo* pSrcFB = nullptr;
MG_Diligent::GLFramebufferInfo* pDstFB = nullptr;
if (readFB != 0) pSrcFB = &MG_Diligent::g_FramebufferMap[readFB];
if (drawFB != 0) pDstFB = &MG_Diligent::g_FramebufferMap[drawFB];
if (!pSrcFB) pSrcFB = &MG_Diligent::g_FramebufferMap[0];
if (!pDstFB) pDstFB = &MG_Diligent::g_FramebufferMap[0];
bool copyColor = (mask & GL_COLOR_BUFFER_BIT) != 0;
bool copyDepth = (mask & GL_DEPTH_BUFFER_BIT) != 0;
bool copyStencil = (mask & GL_STENCIL_BUFFER_BIT) != 0;
if (copyColor && !pSrcFB->ColorRTVs.empty() && !pDstFB->ColorRTVs.empty()) {
for (size_t i = 0; i < pSrcFB->ColorRTVs.size() && i < pDstFB->ColorRTVs.size(); ++i) {
if (pSrcFB->ColorRTVs[i] && pDstFB->ColorRTVs[i]) {
Diligent::CopyTextureAttribs CopyAttribs;
CopyAttribs.pSrcTexture = pSrcFB->ColorRTVs[i]->GetTexture();
CopyAttribs.pDstTexture = pDstFB->ColorRTVs[i]->GetTexture();
CopyAttribs.SrcTextureTransitionMode = Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION;
CopyAttribs.DstTextureTransitionMode = Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION;
Diligent::Box SrcBox;
SrcBox.MinX = srcX0;
SrcBox.MinY = srcY0;
SrcBox.MaxX = srcX1;
SrcBox.MaxY = srcY1;
CopyAttribs.pSrcBox = &SrcBox;
CopyAttribs.DstX = dstX0;
CopyAttribs.DstY = dstY0;
MG_Diligent::g_pContext->CopyTexture(CopyAttribs);
}
}
}
if ((copyDepth || copyStencil) && pSrcFB->pDepthStencilRTV && pDstFB->pDepthStencilRTV) {
Diligent::CopyTextureAttribs CopyAttribs;
CopyAttribs.pSrcTexture = pSrcFB->pDepthStencilRTV->GetTexture();
CopyAttribs.pDstTexture = pDstFB->pDepthStencilRTV->GetTexture();
CopyAttribs.SrcTextureTransitionMode = Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION;
CopyAttribs.DstTextureTransitionMode = Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION;
Diligent::Box SrcBox;
SrcBox.MinX = srcX0;
SrcBox.MinY = srcY0;
SrcBox.MaxX = srcX1;
SrcBox.MaxY = srcY1;
CopyAttribs.pSrcBox = &SrcBox;
CopyAttribs.DstX = dstX0;
CopyAttribs.DstY = dstY0;
MG_Diligent::g_pContext->CopyTexture(CopyAttribs);
}
} }
}
void DrawBuffer(GLenum buf) {
MG_Util::Debug::LogD("glDrawBuffer, buf: %s", MG_Util::Debug::GLEnumToString(buf));
}
void DrawBuffers(GLsizei n, const GLenum *bufs) {
MG_Util::Debug::LogD("glDrawBuffers, n: %d, bufs: [", n);
for (int i = 0; i < n; ++i) {
MG_Util::Debug::LogD("%s,", MG_Util::Debug::GLEnumToString(bufs[i]));
}
MG_Util::Debug::LogD("]");
}
void ReadBuffer(GLenum buf) {
MG_Util::Debug::LogD("glReadBuffer, buf: %s", MG_Util::Debug::GLEnumToString(buf));
}
}
@@ -5,15 +5,18 @@
#ifndef MOBILEGL_GL_FRAMEBUFFER_H #ifndef MOBILEGL_GL_FRAMEBUFFER_H
#define MOBILEGL_GL_FRAMEBUFFER_H #define MOBILEGL_GL_FRAMEBUFFER_H
#include "../../../../Includes.h"
namespace MG_GL::GL { namespace MG_GL::GL {
void UpdateDefaultFramebuffer();
void GenFramebuffers(GLsizei n, GLuint* framebuffers); void GenFramebuffers(GLsizei n, GLuint* framebuffers);
void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers); void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers);
void BindFramebuffer(GLenum target, GLuint framebuffer); void BindFramebuffer(GLenum target, GLuint framebuffer);
void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
GLenum CheckFramebufferStatus(GLenum target); GLenum CheckFramebufferStatus(GLenum target);
void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
void DrawBuffer(GLenum buf);
void DrawBuffers(GLsizei n, const GLenum *bufs);
void ReadBuffer(GLenum mode);
} }
#endif //MOBILEGL_GL_FRAMEBUFFER_H #endif //MOBILEGL_GL_FRAMEBUFFER_H
@@ -2,7 +2,7 @@
// Created by BZLZHH on 2025/3/15. // Created by BZLZHH on 2025/3/15.
// //
#include "GLFuncsDefinitions.h" #include "../../../../Includes.h"
#define DECLARE_GL_FUNCTION_STUB_HEAD(type,name,...) \ #define DECLARE_GL_FUNCTION_STUB_HEAD(type,name,...) \
MG_EXPORT type gl##name(__VA_ARGS__) { MG_EXPORT type gl##name(__VA_ARGS__) {
@@ -57,7 +57,7 @@ DECLARE_GL_FUNCTION_HEAD(void, CompileShader, GLuint shader) DECLARE_GL_FUNCTION
DECLARE_GL_FUNCTION_STUB_HEAD(void, CompressedTexImage2D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CompressedTexImage2D, target,level,internalformat,width,height,border,imageSize,data) DECLARE_GL_FUNCTION_STUB_HEAD(void, CompressedTexImage2D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CompressedTexImage2D, target,level,internalformat,width,height,border,imageSize,data)
DECLARE_GL_FUNCTION_STUB_HEAD(void, CompressedTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CompressedTexSubImage2D, target,level,xoffset,yoffset,width,height,format,imageSize,data) DECLARE_GL_FUNCTION_STUB_HEAD(void, CompressedTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CompressedTexSubImage2D, target,level,xoffset,yoffset,width,height,format,imageSize,data)
DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTexImage2D, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyTexImage2D, target,level,internalformat,x,y,width,height,border) DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTexImage2D, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyTexImage2D, target,level,internalformat,x,y,width,height,border)
DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyTexSubImage2D, target,level,xoffset,yoffset,x,y,width,height) DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, CopyTexSubImage2D, target,level,xoffset,yoffset,x,y,width,height)
DECLARE_GL_FUNCTION_HEAD(GLuint, CreateProgram) DECLARE_GL_FUNCTION_END(GLuint, CreateProgram) DECLARE_GL_FUNCTION_HEAD(GLuint, CreateProgram) DECLARE_GL_FUNCTION_END(GLuint, CreateProgram)
DECLARE_GL_FUNCTION_HEAD(GLuint, CreateShader, GLenum type) DECLARE_GL_FUNCTION_END(GLuint, CreateShader, type) DECLARE_GL_FUNCTION_HEAD(GLuint, CreateShader, GLenum type) DECLARE_GL_FUNCTION_END(GLuint, CreateShader, type)
DECLARE_GL_FUNCTION_STUB_HEAD(void, CullFace, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CullFace, mode) DECLARE_GL_FUNCTION_STUB_HEAD(void, CullFace, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CullFace, mode)
@@ -174,7 +174,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4f, GLuint index, GLfloat x, GLf
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4fv, GLuint index, const GLfloat *v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4fv, index,v) DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4fv, GLuint index, const GLfloat *v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4fv, index,v)
DECLARE_GL_FUNCTION_HEAD(void, VertexAttribPointer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribPointer, index,size,type,normalized,stride,pointer) DECLARE_GL_FUNCTION_HEAD(void, VertexAttribPointer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribPointer, index,size,type,normalized,stride,pointer)
DECLARE_GL_FUNCTION_HEAD(void, Viewport, GLint x, GLint y, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Viewport, x,y,width,height) DECLARE_GL_FUNCTION_HEAD(void, Viewport, GLint x, GLint y, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Viewport, x,y,width,height)
DECLARE_GL_FUNCTION_STUB_HEAD(void, ReadBuffer, GLenum src) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ReadBuffer, src) DECLARE_GL_FUNCTION_STUB_HEAD(void, ReadBuffer, GLenum src) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ReadBuffer, src)
DECLARE_GL_FUNCTION_STUB_HEAD(void, DrawRangeElements, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DrawRangeElements, mode,start,end,count,type,indices) DECLARE_GL_FUNCTION_STUB_HEAD(void, DrawRangeElements, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DrawRangeElements, mode,start,end,count,type,indices)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexImage3D, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexImage3D, target,level,internalformat,width,height,depth,border,format,type,pixels) DECLARE_GL_FUNCTION_STUB_HEAD(void, TexImage3D, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexImage3D, target,level,internalformat,width,height,depth,border,format,type,pixels)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexSubImage3D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexSubImage3D, target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,pixels) DECLARE_GL_FUNCTION_STUB_HEAD(void, TexSubImage3D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexSubImage3D, target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,pixels)
@@ -190,7 +190,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, GetQueryiv, GLenum target, GLenum pname, GLi
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetQueryObjectuiv, GLuint id, GLenum pname, GLuint *params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetQueryObjectuiv, id,pname,params) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetQueryObjectuiv, GLuint id, GLenum pname, GLuint *params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetQueryObjectuiv, id,pname,params)
DECLARE_GL_FUNCTION_HEAD(GLboolean, UnmapBuffer, GLenum target) DECLARE_GL_FUNCTION_END(GLboolean, UnmapBuffer, target) DECLARE_GL_FUNCTION_HEAD(GLboolean, UnmapBuffer, GLenum target) DECLARE_GL_FUNCTION_END(GLboolean, UnmapBuffer, target)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetBufferPointerv, GLenum target, GLenum pname, void **params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetBufferPointerv, target,pname,params) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetBufferPointerv, GLenum target, GLenum pname, void **params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetBufferPointerv, target,pname,params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, DrawBuffers, GLsizei n, const GLenum *bufs) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DrawBuffers, n,bufs) DECLARE_GL_FUNCTION_STUB_HEAD(void, DrawBuffers, GLsizei n, const GLenum *bufs) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DrawBuffers, n,bufs)
DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix2x3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix2x3fv, location,count,transpose,value) DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix2x3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix2x3fv, location,count,transpose,value)
DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix3x2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix3x2fv, location,count,transpose,value) DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix3x2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix3x2fv, location,count,transpose,value)
DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix2x4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix2x4fv, location,count,transpose,value) DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix2x4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix2x4fv, location,count,transpose,value)
@@ -5,6 +5,4 @@
#ifndef MOBILEGL_GL_FUNCS_DEFINITIONS_H #ifndef MOBILEGL_GL_FUNCS_DEFINITIONS_H
#define MOBILEGL_GL_FUNCS_DEFINITIONS_H #define MOBILEGL_GL_FUNCS_DEFINITIONS_H
#include "../../../../Includes.h"
#endif //MOBILEGL_GL_FUNCS_DEFINITIONS_H #endif //MOBILEGL_GL_FUNCS_DEFINITIONS_H
@@ -2,7 +2,7 @@
// Created by BZLZHH on 2025/3/15. // Created by BZLZHH on 2025/3/15.
// //
#include "BackendInfo.h" #include "../../../../Includes.h"
namespace MG_GL::Getter { namespace MG_GL::Getter {
const std::string GetBackendName() { const std::string GetBackendName() {
@@ -12,6 +12,17 @@ namespace MG_GL::Getter {
return "Metal"; return "Metal";
#elif BACKEND_TYPE == BACKEND_GLES #elif BACKEND_TYPE == BACKEND_GLES
return "OpenGL ES"; return "OpenGL ES";
#elif BACKEND_TYPE == BACKEND_DILIGENT
switch (MG_Diligent::DILIGENT_BACKEND_TYPE) {
case MG_Constants::Backend::BACKEND_DILIGENT_VULKAN:
return "DiligentEngine (Vulkan)";
case MG_Constants::Backend::BACKEND_DILIGENT_METAL:
return "DiligentEngine (Metal)";
case MG_Constants::Backend::BACKEND_DILIGENT_OPENGL:
return "DiligentEngine (OpenGL)";
default:
return "DiligentEngine (Unknown Backend)";
}
#else #else
return "<Unknown Backend>"; return "<Unknown Backend>";
#endif #endif
@@ -24,11 +35,78 @@ namespace MG_GL::Getter {
return "MobileGlumtl"; return "MobileGlumtl";
#elif BACKEND_TYPE == BACKEND_GLES #elif BACKEND_TYPE == BACKEND_GLES
return "MobileGlues"; return "MobileGlues";
#elif BACKEND_TYPE == BACKEND_DILIGENT
switch (MG_Diligent::DILIGENT_BACKEND_TYPE) {
case MG_Constants::Backend::BACKEND_DILIGENT_VULKAN:
return "MobileGlued-vk";
case MG_Constants::Backend::BACKEND_DILIGENT_METAL:
return "MobileGlued-mtl";
case MG_Constants::Backend::BACKEND_DILIGENT_OPENGL:
return "MobileGlued-gl";
default:
return "MobileGlued-unknown";
}
#else #else
return "<Unknown MobileGL Version>"; return "<Unknown MobileGL Version>";
#endif #endif
} }
const std::string GetBackendGfxAPIName() {
#if BACKEND_TYPE == BACKEND_VULKAN
return "Vulkan";
#elif BACKEND_TYPE == BACKEND_METAL
return "Metal";
#elif BACKEND_TYPE == BACKEND_GLES
return "OpenGL ES";
#elif BACKEND_TYPE == BACKEND_DILIGENT
switch (MG_Diligent::DILIGENT_BACKEND_TYPE) {
case MG_Constants::Backend::BACKEND_DILIGENT_VULKAN:
return "Vulkan";
case MG_Constants::Backend::BACKEND_DILIGENT_METAL:
return "Metal";
case MG_Constants::Backend::BACKEND_DILIGENT_OPENGL:
return "OpenGL";
default:
return "<unknown>";
}
#else
return "<Unknown Backend>";
#endif
}
const std::string GetGPUName() {
#if BACKEND_TYPE == BACKEND_DILIGENT
if (MG_Diligent::g_pDevice)
return MG_Diligent::g_pDevice->GetAdapterInfo().Description;
return "<not set yet>";
#else
return "<unknown GPU>";
#endif
}
const uint32_t GetBackendGfxAPIVersionMajor() {
#if BACKEND_TYPE == BACKEND_DILIGENT
if (MG_Diligent::g_pDevice)
return MG_Diligent::g_pDevice->GetDeviceInfo().APIVersion.Major;
return 0;
#else
return 0;
#endif
}
const uint32_t GetBackendGfxAPIVersionMinor() {
#if BACKEND_TYPE == BACKEND_DILIGENT
if (MG_Diligent::g_pDevice)
return MG_Diligent::g_pDevice->GetDeviceInfo().APIVersion.Minor;
return 0;
#else
return 0;
#endif
}
void LogMGInfo() { void LogMGInfo() {
std::string MGName = MG_GL::Getter::GetMGName() + " (MobileGL Core)"; std::string MGName = MG_GL::Getter::GetMGName() + " (MobileGL Core)";
@@ -79,6 +157,8 @@ namespace MG_GL::Getter {
std::to_string(minor)+"." + std::to_string(patch); std::to_string(minor)+"." + std::to_string(patch);
#elif BACKEND_TYPE == BACKEND_GLES #elif BACKEND_TYPE == BACKEND_GLES
backendVersion = std::string((const char*)::GLES::glGetString(GL_VERSION)); backendVersion = std::string((const char*)::GLES::glGetString(GL_VERSION));
#elif BACKEND_TYPE == BACKEND_DILIGENT
backendVersion = "Diligent";
#else #else
backendVersion = "<Unknown Backend>"; backendVersion = "<Unknown Backend>";
#endif #endif
@@ -5,10 +5,12 @@
#ifndef MOBILEGL_BACKENDINFO_H #ifndef MOBILEGL_BACKENDINFO_H
#define MOBILEGL_BACKENDINFO_H #define MOBILEGL_BACKENDINFO_H
#include "../../../../Includes.h"
namespace MG_GL::Getter { namespace MG_GL::Getter {
const std::string GetGPUName();
const std::string GetBackendName(); const std::string GetBackendName();
const std::string GetBackendGfxAPIName();
const uint32_t GetBackendGfxAPIVersionMajor();
const uint32_t GetBackendGfxAPIVersionMinor();
const std::string GetMGName(); const std::string GetMGName();
void LogMGInfo(); void LogMGInfo();
} }
@@ -2,7 +2,7 @@
// Created by BZLZHH on 2025/3/15. // Created by BZLZHH on 2025/3/15.
// //
#include "GL_Getter.h" #include "../../../../Includes.h"
namespace MG_GL::GL { namespace MG_GL::GL {
static std::string rendererString; static std::string rendererString;
@@ -15,7 +15,7 @@ namespace MG_GL::GL {
MG_Util::Debug::LogD("glGetString, name: %s", MG_Util::Debug::GLEnumToString(name)); MG_Util::Debug::LogD("glGetString, name: %s", MG_Util::Debug::GLEnumToString(name));
switch (name) { switch (name) {
case GL_VENDOR: case GL_VENDOR:
return (const GLubyte *)"MobileGL-Dev"; return (const GLubyte *)"MobileGL-Dev (BZLZHH, Swung0x48, Tungsten)";
case GL_VERSION: { case GL_VERSION: {
static std::string versionStr; static std::string versionStr;
if (versionStr.empty()) { if (versionStr.empty()) {
@@ -44,7 +44,11 @@ namespace MG_GL::GL {
} }
return (const GLubyte *)rendererString.c_str(); return (const GLubyte *)rendererString.c_str();
*/ */
return (const GLubyte *)(MG_GL::Getter::GetMGName() + " (MobileGL Core) Renderer").c_str(); return (const GLubyte *)std::format("{} | {} {}.{}",
MG_GL::Getter::GetGPUName(),
MG_GL::Getter::GetBackendGfxAPIName(),
MG_GL::Getter::GetBackendGfxAPIVersionMajor(),
MG_GL::Getter::GetBackendGfxAPIVersionMinor()).c_str();
} }
case GL_SHADING_LANGUAGE_VERSION: case GL_SHADING_LANGUAGE_VERSION:
return (const GLubyte *) "4.50 MobileGL with glslang"; return (const GLubyte *) "4.50 MobileGL with glslang";
@@ -183,7 +187,7 @@ namespace MG_GL::GL {
break; break;
case GL_MAX_VERTEX_ATTRIBS: case GL_MAX_VERTEX_ATTRIBS:
// TODO: Check the real value // TODO: Check the real value
params[0] = 64; params[0] = MG_Constants::VertexArray::MAX_VERTEX_ATTRIBS;
break; break;
// Texture state // Texture state
@@ -5,8 +5,6 @@
#ifndef MOBILEGL_GL_GETTER_H #ifndef MOBILEGL_GL_GETTER_H
#define MOBILEGL_GL_GETTER_H #define MOBILEGL_GL_GETTER_H
#include "../../../../Includes.h"
namespace MG_GL::GL { namespace MG_GL::GL {
const GLubyte* GetString(GLenum name); const GLubyte* GetString(GLenum name);
const GLubyte* GetStringi(GLenum name, GLuint index); const GLubyte* GetStringi(GLenum name, GLuint index);
@@ -2,15 +2,197 @@
// Created by BZLZHH on 2025/3/15. // Created by BZLZHH on 2025/3/15.
// //
#include "GL_Program.h" #include "../../../../Includes.h"
namespace MG_GL::GL { namespace MG_GL::GL {
void CreateDefaultUBO(MG_Diligent::GLProgramInfo& programInfo, size_t uboSize) {
MG_Util::Debug::LogD("CreateDefaultUBO for program, size = %zu", uboSize);
if (uboSize > 0) {
Diligent::BufferDesc BuffDesc;
BuffDesc.Name = "MG_DEFAULT_UBO";
BuffDesc.Size = uboSize;
BuffDesc.Usage = Diligent::USAGE_DYNAMIC;
BuffDesc.BindFlags = Diligent::BIND_UNIFORM_BUFFER;
BuffDesc.CPUAccessFlags = Diligent::CPU_ACCESS_WRITE;
MG_Diligent::g_pDevice->CreateBuffer(BuffDesc, nullptr, &programInfo.pDefaultUBO);
MG_Util::Debug::LogD("Created default UBO: size = %zu", uboSize);
} else {
MG_Util::Debug::LogD("UBO size is 0, default UBO not created.");
}
}
size_t RecordUniformOffsets(MG_Diligent::GLProgramInfo& programInfo, const MG_Global::unordered_map<GLuint, std::string>& shaderSources) {
MG_Util::Debug::LogD("RecordUniformOffsets for program %u using SPIRV-Cross", programInfo.id);
size_t uboTotalSize = 0;
programInfo.uniformOffsets.clear();
GLuint reflectionShaderId = 0;
for (auto shaderId : programInfo.AttachedShadersID) {
auto& shaderObj = MG_State_T::programState->shaders_[shaderId];
MG_Util::Debug::LogD(" Checking attached shader %u, type: %s", shaderId, MG_Util::Debug::GLEnumToString(shaderObj.type));
if (shaderObj.type == GL_VERTEX_SHADER) {
reflectionShaderId = shaderId;
MG_Util::Debug::LogD(" Found vertex shader %u for reflection.", reflectionShaderId);
break;
}
}
if (!reflectionShaderId && !programInfo.AttachedShadersID.empty()) {
reflectionShaderId = programInfo.AttachedShadersID[0];
MG_Util::Debug::LogD(" No vertex shader found, using first attached shader %u for reflection.", reflectionShaderId);
}
if (!reflectionShaderId) {
MG_Util::Debug::LogW(" No suitable shader found for UBO reflection.");
return uboTotalSize;
}
MG_Util::Debug::LogD(" Using shader %u for UBO reflection.", reflectionShaderId);
auto itSource = shaderSources.find(reflectionShaderId);
if (itSource == shaderSources.end()) {
MG_Util::Debug::LogE(" Could not find source for reflection shader %u.", reflectionShaderId);
return uboTotalSize;
}
MG_Util::Debug::LogD(" Found source for shader %u.", reflectionShaderId);
MG_Util::Debug::LogD(" Shader source for reflection:\n%s", itSource->second.c_str());
std::string infoLog;
auto spirv = MG_Util::Program::CompileGLSLToSPIRV(
MG_State_T::programState->shaders_[reflectionShaderId].type,
itSource->second,
infoLog,
true
);
if (spirv.empty()) {
MG_Util::Debug::LogE("GLSL to SPIR-V compilation failed for shader %u: %s", reflectionShaderId, infoLog.c_str());
return uboTotalSize;
}
MG_Util::Debug::LogD(" Successfully compiled GLSL to SPIR-V for shader %u.", reflectionShaderId);
spvc_context context = nullptr;
spvc_parsed_ir ir = nullptr;
spvc_compiler compiler = nullptr;
spvc_resources resources = nullptr;
if (spvc_context_create(&context) != SPVC_SUCCESS) {
MG_Util::Debug::LogE("SPIRV-Cross: Failed to create context: %s", spvc_context_get_last_error_string(context));
return uboTotalSize;
}
if (spvc_context_parse_spirv(context, spirv.data(), spirv.size(), &ir) != SPVC_SUCCESS) {
MG_Util::Debug::LogE("SPIRV-Cross: Failed to parse SPIR-V: %s", spvc_context_get_last_error_string(context));
spvc_context_destroy(context);
return uboTotalSize;
}
if (spvc_context_create_compiler(context, SPVC_BACKEND_GLSL, ir, SPVC_CAPTURE_MODE_TAKE_OWNERSHIP, &compiler) != SPVC_SUCCESS) {
MG_Util::Debug::LogE("SPIRV-Cross: Failed to create compiler: %s", spvc_context_get_last_error_string(context));
spvc_context_destroy(context);
return uboTotalSize;
}
MG_Util::Debug::LogD(" spvc_context_create_compiler successful.");
if (spvc_compiler_create_shader_resources(compiler, &resources) != SPVC_SUCCESS) {
MG_Util::Debug::LogE("SPIRV-Cross: Failed to create shader resources: %s", spvc_context_get_last_error_string(context));
spvc_context_destroy(context);
return uboTotalSize;
}
MG_Util::Debug::LogD(" spvc_compiler_create_shader_resources successful.");
const spvc_reflected_resource* ubo_list = nullptr;
size_t ubo_count = 0;
if (spvc_resources_get_resource_list_for_type(resources, SPVC_RESOURCE_TYPE_UNIFORM_BUFFER, &ubo_list, &ubo_count) != SPVC_SUCCESS) {
MG_Util::Debug::LogE("SPIRV-Cross: Failed to get resource list for UBO: %s", spvc_context_get_last_error_string(context));
spvc_context_destroy(context);
return uboTotalSize;
}
MG_Util::Debug::LogD(" Found %zu UBO resources.", ubo_count);
for (size_t i = 0; i < ubo_count; i++) {
const char* name = ubo_list[i].name;
if (!name || strcmp(name, "MG_DEFAULT_UBO") != 0) {
MG_Util::Debug::LogD(" Skipping UBO '%s'.", name ? name : "<unnamed>");
continue;
}
MG_Util::Debug::LogD(" Found UBO 'MG_DEFAULT_UBO'.");
spvc_type_id ubo_type_id = ubo_list[i].type_id;
spvc_type ubo_type = spvc_compiler_get_type_handle(compiler, ubo_type_id);
size_t currentUboSize = 0;
if (spvc_compiler_get_declared_struct_size(compiler, ubo_type, &currentUboSize) != SPVC_SUCCESS) {
MG_Util::Debug::LogE("SPIRV-Cross: Failed to get declared struct size: %s", spvc_context_get_last_error_string(context));
spvc_context_destroy(context);
return uboTotalSize;
}
uboTotalSize = currentUboSize;
MG_Util::Debug::LogD(" UBO 'MG_DEFAULT_UBO' total size: %zu", uboTotalSize);
size_t member_count = spvc_type_get_num_member_types(ubo_type);
for (size_t member_index = 0; member_index < member_count; member_index++) {
const char* member_name = programInfo.uniformBufferNames[member_index].c_str();
unsigned offset;
spvc_compiler_type_struct_member_offset(compiler, ubo_type, member_index, &offset);
if (member_name) {
programInfo.uniformOffsets[member_name] = offset;
MG_Util::Debug::LogD(
" Uniform '%s' offset = %u (via SPIRV-Cross)",
member_name,
offset
);
}
}
break;
}
spvc_context_destroy(context);
MG_Util::Debug::LogD("RecordUniformOffsets completed for program %u, UBO total size: %zu", programInfo.id, uboTotalSize);
return uboTotalSize;
}
Diligent::VALUE_TYPE ConvertGLTypeToDiligent(GLenum type) {
switch (type) {
case GL_FLOAT: return Diligent::VT_FLOAT32;
case GL_FLOAT_VEC2: return Diligent::VT_FLOAT32;
case GL_FLOAT_VEC3: return Diligent::VT_FLOAT32;
case GL_FLOAT_VEC4: return Diligent::VT_FLOAT32;
case GL_SHORT: return Diligent::VT_INT16;
case GL_UNSIGNED_SHORT: return Diligent::VT_UINT16;
case GL_BYTE: return Diligent::VT_INT8;
case GL_UNSIGNED_BYTE: return Diligent::VT_UINT8;
case GL_INT: return Diligent::VT_INT32;
case GL_INT_VEC2: return Diligent::VT_INT32;
case GL_INT_VEC3: return Diligent::VT_INT32;
case GL_INT_VEC4: return Diligent::VT_INT32;
case GL_UNSIGNED_INT: return Diligent::VT_UINT32;
case GL_UNSIGNED_INT_VEC2: return Diligent::VT_UINT32;
case GL_UNSIGNED_INT_VEC3: return Diligent::VT_UINT32;
case GL_UNSIGNED_INT_VEC4: return Diligent::VT_UINT32;
case GL_FLOAT_MAT2: return Diligent::VT_FLOAT32;
case GL_FLOAT_MAT3: return Diligent::VT_FLOAT32;
case GL_FLOAT_MAT4: return Diligent::VT_FLOAT32;
case GL_FLOAT_MAT2x3: return Diligent::VT_FLOAT32;
case GL_FLOAT_MAT2x4: return Diligent::VT_FLOAT32;
case GL_FLOAT_MAT3x2: return Diligent::VT_FLOAT32;
case GL_FLOAT_MAT3x4: return Diligent::VT_FLOAT32;
case GL_FLOAT_MAT4x2: return Diligent::VT_FLOAT32;
case GL_FLOAT_MAT4x3: return Diligent::VT_FLOAT32;
default: return Diligent::VT_UNDEFINED;
}
}
GLuint CreateShader(GLenum type) { GLuint CreateShader(GLenum type) {
MG_Util::Debug::LogD("glCreateShader, type: %s", MG_Util::Debug::GLEnumToString(type)); MG_Util::Debug::LogD("glCreateShader, type: %s", MG_Util::Debug::GLEnumToString(type));
GLuint shader; GLuint shader;
GLenum result = MG_State::CreateShader(type, &shader); GLenum result = MG_State::CreateShader(type, &shader);
if (result == GL_NO_ERROR) { if (result == GL_NO_ERROR) {
MG_Util::Debug::LogD("Created shader ID: %u", shader); MG_Util::Debug::LogD("Created shader ID: %u", shader);
MG_Diligent::g_ShaderMap[shader] = nullptr;
return shader; return shader;
} }
MG_State::SetError(result); MG_State::SetError(result);
@@ -34,15 +216,29 @@ namespace MG_GL::GL {
void DeleteShader(GLuint shader) { void DeleteShader(GLuint shader) {
MG_Util::Debug::LogD("glDeleteShader, shader: %u", shader); MG_Util::Debug::LogD("glDeleteShader, shader: %u", shader);
GLenum result = MG_State::DeleteShader(shader); GLenum result = MG_State::DeleteShader(shader);
if (result == GL_NO_ERROR) return; if (result == GL_NO_ERROR) {
// Do not delete the shader object since it may be used in glDraw*.
/*
auto it = MG_Diligent::g_ShaderMap.find(shader);
if (it != MG_Diligent::g_ShaderMap.end()) {
if (it->second) {
it->second->Release();
}
MG_Diligent::g_ShaderMap.erase(it);
}
return;
*/
}
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Error deleting shader: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogW("Error deleting shader: %s", MG_Util::Debug::GLEnumToString(result));
} }
void DeleteProgram(GLuint program) { void DeleteProgram(GLuint program) {
MG_Util::Debug::LogD("glDeleteProgram, program: %u", program); MG_Util::Debug::LogD("glDeleteProgram, program: %u", program);
GLenum result = MG_State::DeleteProgram(program); GLenum result = MG_State::DeleteProgram(program);
if (result == GL_NO_ERROR) return; if (result == GL_NO_ERROR) {
return;
}
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Error deleting program: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogE("Error deleting program: %s", MG_Util::Debug::GLEnumToString(result));
} }
@@ -50,13 +246,20 @@ namespace MG_GL::GL {
void AttachShader(GLuint program, GLuint shader) { void AttachShader(GLuint program, GLuint shader) {
MG_Util::Debug::LogD("glAttachShader, program: %u, shader: %u", program, shader); MG_Util::Debug::LogD("glAttachShader, program: %u, shader: %u", program, shader);
GLenum result = MG_State::LinkShaderToProgram(program, shader); GLenum result = MG_State::LinkShaderToProgram(program, shader);
if (result == GL_NO_ERROR) return; if (result == GL_NO_ERROR) {
return;
}
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Error attaching shader: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogE("Error attaching shader: %s", MG_Util::Debug::GLEnumToString(result));
} }
void ShaderSource(GLuint shader, GLsizei count, const GLchar *const*string, const GLint* length) { void ShaderSource(GLuint shader, GLsizei count, const GLchar *const*string, const GLint* length) {
MG_Util::Debug::LogD("glShaderSource, shader: %u, count: %d", shader, count); MG_Util::Debug::LogD("glShaderSource, shader: %u, count: %d", shader, count);
if (count > 0 && string != nullptr && string[0] != nullptr) {
MG_Util::Debug::LogD("Shader source for shader %u:\n%s", shader, string[0]);
} else {
MG_Util::Debug::LogD("Shader source for shader %u is empty or null.", shader);
}
GLenum result = MG_State::UploadShaderSource(shader, count, (const GLchar **)string, length); GLenum result = MG_State::UploadShaderSource(shader, count, (const GLchar **)string, length);
if (result == GL_NO_ERROR) return; if (result == GL_NO_ERROR) return;
MG_State::SetError(result); MG_State::SetError(result);
@@ -65,31 +268,206 @@ namespace MG_GL::GL {
void CompileShader(GLuint shader) { void CompileShader(GLuint shader) {
MG_Util::Debug::LogD("glCompileShader, shader: %u", shader); MG_Util::Debug::LogD("glCompileShader, shader: %u", shader);
// Defer actual compilation to LinkProgram
GLenum result = MG_State::BuildShaderStage(shader); GLenum result = MG_State::BuildShaderStage(shader);
if (result == GL_NO_ERROR) return; if (result == GL_NO_ERROR) return;
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Error compiling shader: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogE("Error marking shader for compilation: %s", MG_Util::Debug::GLEnumToString(result));
} }
void LinkProgram(GLuint program) { void LinkProgram(GLuint program) {
MG_Util::Debug::LogD("glLinkProgram, program: %u", program); MG_Util::Debug::LogD("glLinkProgram, program: %u", program);
GLenum result = MG_State::FinalizeProgramPipeline(program); GLenum result = MG_State::FinalizeProgramPipeline(program);
if (result == GL_NO_ERROR) return; if (result != GL_NO_ERROR) {
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Error linking program: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogE("Error linking program: %s", MG_Util::Debug::GLEnumToString(result));
return;
}
auto& programInfo = MG_Diligent::g_ProgramMap[program];
auto& programObj = MG_State_T::programState->programs_[program];
programInfo.id = program;
for (const auto& shaderId : programObj.attachedShaders) {
programInfo.AttachedShadersID.push_back(shaderId);
}
MG_Global::unordered_map<GLuint, std::string> shaderSources;
MG_Global::unordered_map<GLuint, std::string> finalShaderSources;
for (GLuint shaderId : programObj.attachedShaders) {
auto it = MG_State_T::programState->shaders_.find(shaderId);
if (it != MG_State_T::programState->shaders_.end() && !it->second.markedForDeletion) {
shaderSources[it->first] = it->second.source;
// MG_Util::Program::RenameGLSLBuiltinsForVulkan(shaderSources[it->first]);
}
}
MG_Util::Program::GenerateDefaultUBOForGLSL_Multi(shaderSources, programInfo.uniformBufferNames);
MG_Util::Debug::LogD("LinkProgram: uniformBufferNames for %u:", program);
for (auto& name: programInfo.uniformBufferNames) {
MG_Util::Debug::LogD(" %s", name.c_str());
}
for (GLuint shaderId : programObj.attachedShaders) {
auto it = MG_State_T::programState->shaders_.find(shaderId);
if (it != MG_State_T::programState->shaders_.end() && !it->second.markedForDeletion) {
std::string shaderSource;
if (it->second.type == GL_VERTEX_SHADER) {
std::string infoLog;
const char* fragmentShaderSource = nullptr;
for (GLuint otherShaderId : programObj.attachedShaders) {
if (otherShaderId != shaderId && MG_State_T::programState->shaders_[otherShaderId].type == GL_FRAGMENT_SHADER) {
fragmentShaderSource = shaderSources[otherShaderId].c_str();
break;
}
}
auto spirv = MG_Util::Program::CompileGLSLToSPIRV(it->second.type,
shaderSources[shaderId],
infoLog, true, GL_FRAGMENT_SHADER, fragmentShaderSource);
if (spirv.empty()) {
MG_Util::Debug::LogE("Failed to compile vertex shader %u: %s", shaderId,
infoLog.c_str());
continue;
}
shaderSource = MG_Util::Program::BindInputLayoutLocationsForGLSL(spirv,
programObj.attribLocations);
} else if (it->second.type == GL_FRAGMENT_SHADER) {
std::string infoLog;
const char* vertexShaderSource = nullptr;
for (GLuint otherShaderId : programObj.attachedShaders) {
if (otherShaderId != shaderId && MG_State_T::programState->shaders_[otherShaderId].type == GL_VERTEX_SHADER) {
vertexShaderSource = shaderSources[otherShaderId].c_str();
break;
}
}
auto spirv = MG_Util::Program::CompileGLSLToSPIRV(it->second.type,
shaderSources[shaderId],
infoLog, true,
GL_VERTEX_SHADER, vertexShaderSource);
if (spirv.empty()) {
MG_Util::Debug::LogE("Failed to compile fragment shader %u to SPIRV: %s", shaderId,
infoLog.c_str());
continue;
}
shaderSource = MG_Util::Program::CompileSPIRVToGLSL(spirv, 450, false, true);
} else {
shaderSource = it->second.source;
}
finalShaderSources[it->first] = shaderSource;
}
}
MG_Util::Debug::LogD("Shader sources after UBO generation for program %u:", program);
for (const auto& [shaderId, source] : finalShaderSources) {
MG_Util::Debug::LogD(" Program %u Shader %u:\n%s", program, shaderId, source.c_str());
}
size_t uboTotalSize = RecordUniformOffsets(programInfo, finalShaderSources);
CreateDefaultUBO(programInfo, uboTotalSize);
// Compile attached shaders
for (GLuint shaderId : programInfo.AttachedShadersID) {
auto& shaderObj = MG_State_T::programState->shaders_[shaderId];
// Compile only if not already compiled in Diligent
if (MG_Diligent::g_ShaderMap.find(shaderId) == MG_Diligent::g_ShaderMap.end() || MG_Diligent::g_ShaderMap[shaderId] == nullptr) {
GLenum shaderType = shaderObj.type;
std::string sourceStr = finalShaderSources[shaderId];
MG_Util::Program::RenameGLSLBuiltinsForVulkan(sourceStr);
MG_Util::Debug::LogD("Shader ID: %u, type: %s\nConverted source:\n%s",
shaderId, MG_Util::Debug::GLEnumToString(shaderType), sourceStr.c_str());
Diligent::ShaderCreateInfo ShaderCI;
ShaderCI.Source = sourceStr.c_str();
ShaderCI.EntryPoint = "main";
switch (shaderType) {
case GL_VERTEX_SHADER: ShaderCI.Desc.ShaderType = Diligent::SHADER_TYPE_VERTEX; break;
case GL_FRAGMENT_SHADER: ShaderCI.Desc.ShaderType = Diligent::SHADER_TYPE_PIXEL; break;
case GL_GEOMETRY_SHADER: ShaderCI.Desc.ShaderType = Diligent::SHADER_TYPE_GEOMETRY; break;
case GL_TESS_CONTROL_SHADER: ShaderCI.Desc.ShaderType = Diligent::SHADER_TYPE_HULL; break;
case GL_TESS_EVALUATION_SHADER: ShaderCI.Desc.ShaderType = Diligent::SHADER_TYPE_DOMAIN; break;
case GL_COMPUTE_SHADER: ShaderCI.Desc.ShaderType = Diligent::SHADER_TYPE_COMPUTE; break;
default: MG_Util::Debug::LogW("Unsupported shader type for compilation: %u", shaderType); continue;
}
ShaderCI.Desc.Name = ("Shader_" + std::to_string(shaderId)).c_str();
ShaderCI.SourceLanguage = Diligent::SHADER_SOURCE_LANGUAGE_GLSL_VERBATIM;
Diligent::IShader* pShader = nullptr;
Diligent::RefCntAutoPtr<Diligent::IDataBlob> pMsg;
MG_Diligent::g_pDevice->CreateShader(ShaderCI, &pShader, &pMsg);
if (pShader) {
MG_Diligent::g_ShaderMap[shaderId] = pShader;
programInfo.AttachedShaders.push_back(pShader);
shaderObj.compiled = UncertainBool::True;
shaderObj.compileStatus = GL_TRUE;
MG_Util::Debug::LogD("Successfully compiled shader ID: %u for program %u", shaderId, program);
} else {
shaderObj.compiled = UncertainBool::False;
shaderObj.compileStatus = GL_FALSE;
MG_Util::Debug::LogE("Failed to compile shader ID: %u for program %u. \ncompiler info:\n%s", shaderId, program, pMsg->GetConstDataPtr<char>());
}
} else {
// Shader already compiled, just add to programInfo
programInfo.AttachedShaders.push_back(MG_Diligent::g_ShaderMap[shaderId]);
}
}
programInfo.inputLayout.clear();
auto* pVAO = MG_State_T::vertexArrayState->GetCurrentVAO();
if (!pVAO) return;
// for (const auto& [index, attrib] : pVAO->attribs) {
for (uint32_t index = 0; index < MG_Constants::VertexArray::MAX_VERTEX_ATTRIBS; ++index) {
const auto& attrib = pVAO->attribs[index];
if (attrib.enabled) {
Diligent::LayoutElement elem;
elem.InputIndex = index;
elem.BufferSlot = 0;
elem.NumComponents = attrib.size;
elem.ValueType = ConvertGLTypeToDiligent(attrib.type);
elem.IsNormalized = attrib.normalized;
elem.RelativeOffset = static_cast<GLuint>(reinterpret_cast<size_t>(attrib.pointer));
programInfo.inputLayout.push_back(elem);
}
}
programInfo.psoDirty = true;
programInfo.psoStateHash = 0;
programInfo.uniformStages.clear();
programInfo.programObj = MG_State_T::programState->programs_[program];
if (programInfo.pResourceBinding) {
programInfo.pResourceBinding->Release();
programInfo.pResourceBinding = nullptr;
}
programObj.linked = true;
programObj.linkStatus = GL_TRUE;
} }
void UseProgram(GLuint program) { void UseProgram(GLuint program) {
MG_Util::Debug::LogD("glUseProgram, program: %u", program); MG_Util::Debug::LogD("glUseProgram, program: %u", program);
GLenum result = MG_State::ActivateRenderProgram(program); GLenum result = MG_State::ActivateRenderProgram(program);
if (result == GL_NO_ERROR) return; if (result == GL_NO_ERROR) {
return;
}
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Error using program: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogE("Error using program: %s", MG_Util::Debug::GLEnumToString(result));
} }
void BindAttribLocation(GLuint program, GLuint index, const GLchar* name) { void BindAttribLocation(GLuint program, GLuint index, const GLchar* name) {
MG_Util::Debug::LogD("glBindAttribLocation, program: %u, index: %u, name: %s", program, index, name); MG_Util::Debug::LogD("glBindAttribLocation, program: %u, index: %u, name: %s", program, index, name);
GLenum result = MG_State::DefineProgramAttributeBinding(program, index, name); GLenum result = MG_State::DefineProgramAttributeLocation(program, index, name);
if (result == GL_NO_ERROR) return; if (result == GL_NO_ERROR) return;
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Error binding attribute: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogE("Error binding attribute: %s", MG_Util::Debug::GLEnumToString(result));
@@ -97,7 +475,7 @@ namespace MG_GL::GL {
GLint GetAttribLocation(GLuint program, const GLchar* name) { GLint GetAttribLocation(GLuint program, const GLchar* name) {
MG_Util::Debug::LogD("glGetAttribLocation, program: %u, name: %s", program, name); MG_Util::Debug::LogD("glGetAttribLocation, program: %u, name: %s", program, name);
GLint location = MG_State::QueryProgramAttributeBinding(program, name); GLint location = MG_State::QueryProgramAttributeLocation(program, name);
if (location != -1) return location; if (location != -1) return location;
MG_State::SetError(GL_INVALID_OPERATION); MG_State::SetError(GL_INVALID_OPERATION);
MG_Util::Debug::LogE("Attribute not found: %s", name); MG_Util::Debug::LogE("Attribute not found: %s", name);
@@ -119,7 +497,7 @@ namespace MG_GL::GL {
GLenum result = MG_State::QueryProgramStateIntVector(program, pname, params); GLenum result = MG_State::QueryProgramStateIntVector(program, pname, params);
if (result == GL_NO_ERROR) return; if (result == GL_NO_ERROR) return;
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Error getting program param: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogW("Error getting program param: %s", MG_Util::Debug::GLEnumToString(result));
} }
void GetShaderiv(GLuint shader, GLenum pname, GLint* params) { void GetShaderiv(GLuint shader, GLenum pname, GLint* params) {
@@ -5,9 +5,9 @@
#ifndef MOBILEGL_GL_PROGRAM_H #ifndef MOBILEGL_GL_PROGRAM_H
#define MOBILEGL_GL_PROGRAM_H #define MOBILEGL_GL_PROGRAM_H
#include "../../../../Includes.h"
namespace MG_GL::GL { namespace MG_GL::GL {
Diligent::VALUE_TYPE ConvertGLTypeToDiligent(GLenum type);
GLuint CreateShader(GLenum type); GLuint CreateShader(GLenum type);
GLuint CreateProgram(); GLuint CreateProgram();
void DeleteShader(GLuint shader); void DeleteShader(GLuint shader);
@@ -2,9 +2,187 @@
// Created by BZLZHH on 2025/3/15. // Created by BZLZHH on 2025/3/15.
// //
#include "GL_Texture.h" #include "../../../../Includes.h"
namespace MG_GL::GL { namespace MG_GL::GL {
Diligent::TEXTURE_FORMAT ConvertInternalFormat(GLint internalFormat) {
switch (internalFormat) {
case GL_RGBA: return Diligent::TEX_FORMAT_RGBA8_UNORM;
case GL_RGBA8: return Diligent::TEX_FORMAT_RGBA8_UNORM;
case GL_RGBA8_SNORM: return Diligent::TEX_FORMAT_RGBA8_SNORM;
case GL_RGBA16F: return Diligent::TEX_FORMAT_RGBA16_FLOAT;
case GL_RGBA32F: return Diligent::TEX_FORMAT_RGBA32_FLOAT;
case GL_RGB: return Diligent::TEX_FORMAT_RGBA8_UNORM;
case GL_RGB8: return Diligent::TEX_FORMAT_RGBA8_UNORM; // Diligent doesn't have RGB8, promote to RGBA8
case GL_RGB16F: return Diligent::TEX_FORMAT_RGBA16_FLOAT; // Promote
case GL_RGB32F: return Diligent::TEX_FORMAT_RGBA32_FLOAT; // Promote
case GL_DEPTH_COMPONENT: return Diligent::TEX_FORMAT_D32_FLOAT;
case GL_DEPTH_COMPONENT16: return Diligent::TEX_FORMAT_D16_UNORM;
case GL_DEPTH_COMPONENT24: return Diligent::TEX_FORMAT_D24_UNORM_S8_UINT; // No D24_UNORM, use with stencil
case GL_DEPTH_COMPONENT32: return Diligent::TEX_FORMAT_D32_FLOAT;
case GL_DEPTH_COMPONENT32F: return Diligent::TEX_FORMAT_D32_FLOAT;
case GL_DEPTH_STENCIL: return Diligent::TEX_FORMAT_D24_UNORM_S8_UINT;
case GL_DEPTH24_STENCIL8: return Diligent::TEX_FORMAT_D24_UNORM_S8_UINT;
case GL_DEPTH32F_STENCIL8: return Diligent::TEX_FORMAT_D32_FLOAT_S8X24_UINT;
case GL_RED: return Diligent::TEX_FORMAT_R8_UNORM;
case GL_R8: return Diligent::TEX_FORMAT_R8_UNORM;
case GL_R16F: return Diligent::TEX_FORMAT_R16_FLOAT;
case GL_R32F: return Diligent::TEX_FORMAT_R32_FLOAT;
case GL_RG: return Diligent::TEX_FORMAT_RG8_UNORM;
case GL_RG8: return Diligent::TEX_FORMAT_RG8_UNORM;
case GL_RG16F: return Diligent::TEX_FORMAT_RG16_FLOAT;
case GL_RG32F: return Diligent::TEX_FORMAT_RG32_FLOAT;
default: return Diligent::TEX_FORMAT_RGBA8_UNORM;
}
}
size_t GetBytesPerPixel(GLenum format, GLenum type) {
int components = 0;
switch (format) {
case GL_RED: components = 1; break;
case GL_RG: components = 2; break;
case GL_RGB: components = 3; break;
case GL_RGBA: components = 4; break;
case GL_DEPTH_COMPONENT: components = 1; break;
case GL_DEPTH_STENCIL: components = 2; break;
default: components = 4; break;
}
size_t typeSize = 0;
switch (type) {
case GL_UNSIGNED_BYTE:
case GL_BYTE: typeSize = 1; break;
case GL_UNSIGNED_SHORT:
case GL_SHORT: typeSize = 2; break;
case GL_UNSIGNED_INT:
case GL_INT:
case GL_FLOAT: typeSize = 4; break;
default: typeSize = 1; break;
}
return components * typeSize;
}
Diligent::FILTER_TYPE ConvertCompareFilter(Diligent::FILTER_TYPE& filter, bool compare) {
if (compare) {
switch (filter) {
case Diligent::FILTER_TYPE_POINT: return Diligent::FILTER_TYPE_COMPARISON_POINT;
case Diligent::FILTER_TYPE_LINEAR: return Diligent::FILTER_TYPE_COMPARISON_LINEAR;
case Diligent::FILTER_TYPE_ANISOTROPIC: return Diligent::FILTER_TYPE_COMPARISON_ANISOTROPIC;
default: return filter;
}
} else {
switch (filter) {
case Diligent::FILTER_TYPE_COMPARISON_POINT: return Diligent::FILTER_TYPE_POINT;
case Diligent::FILTER_TYPE_COMPARISON_LINEAR: return Diligent::FILTER_TYPE_LINEAR;
case Diligent::FILTER_TYPE_COMPARISON_ANISOTROPIC: return Diligent::FILTER_TYPE_ANISOTROPIC;
default: return filter;
}
}
}
bool IsCompareFilter(Diligent::FILTER_TYPE filter) {
switch (filter) {
case Diligent::FILTER_TYPE_COMPARISON_POINT: return true;
case Diligent::FILTER_TYPE_COMPARISON_LINEAR: return true;
case Diligent::FILTER_TYPE_COMPARISON_ANISOTROPIC: return true;
default: return false;
}
}
void FillFilterTypeFromGLEnum(GLenum pname, GLenum param, Diligent::FILTER_TYPE& minFilter, Diligent::FILTER_TYPE& magFilter, Diligent::FILTER_TYPE& mipFilter) {
if (pname == GL_TEXTURE_COMPARE_MODE) {
bool compare = (param == GL_COMPARE_REF_TO_TEXTURE);
minFilter = ConvertCompareFilter(minFilter, compare);
magFilter = ConvertCompareFilter(magFilter, compare);
mipFilter = ConvertCompareFilter(mipFilter, compare);
return;
}
Diligent::FILTER_TYPE* pFilter = nullptr;
if (pname == GL_TEXTURE_MIN_FILTER) {
pFilter = &minFilter;
} else if (pname == GL_TEXTURE_MAG_FILTER) {
pFilter = &magFilter;
} else {
MG_Util::Debug::LogD("FillFilterTypeFromGLEnum: not allowed pname!");
return;
}
Diligent::FILTER_TYPE& filter = *pFilter;
bool filterIsCompare = IsCompareFilter(filter);
bool mipFilterIsCompare = IsCompareFilter(mipFilter);
switch (param) {
case GL_NEAREST:
filter = Diligent::FILTER_TYPE_POINT;
if (pname == GL_TEXTURE_MIN_FILTER)
mipFilter = Diligent::FILTER_TYPE_POINT;
break;
case GL_LINEAR:
filter = Diligent::FILTER_TYPE_LINEAR;
if (pname == GL_TEXTURE_MIN_FILTER)
mipFilter = Diligent::FILTER_TYPE_POINT;
break;
case GL_NEAREST_MIPMAP_NEAREST:
filter = Diligent::FILTER_TYPE_POINT;
mipFilter = Diligent::FILTER_TYPE_POINT;
break;
case GL_LINEAR_MIPMAP_NEAREST:
filter = Diligent::FILTER_TYPE_LINEAR;
mipFilter = Diligent::FILTER_TYPE_POINT;
break;
case GL_NEAREST_MIPMAP_LINEAR:
filter = Diligent::FILTER_TYPE_POINT;
mipFilter = Diligent::FILTER_TYPE_LINEAR;
break;
case GL_LINEAR_MIPMAP_LINEAR:
filter = Diligent::FILTER_TYPE_LINEAR;
mipFilter = Diligent::FILTER_TYPE_LINEAR;
break;
default:
break;
}
filter = ConvertCompareFilter(filter, filterIsCompare);
mipFilter = ConvertCompareFilter(mipFilter, mipFilterIsCompare);
}
Diligent::COMPARISON_FUNCTION ConvertComparsionFunc(GLint param) {
switch (param) {
case GL_LEQUAL: return Diligent::COMPARISON_FUNC_LESS_EQUAL;
case GL_GEQUAL: return Diligent::COMPARISON_FUNC_GREATER_EQUAL;
case GL_LESS: return Diligent::COMPARISON_FUNC_LESS;
case GL_GREATER: return Diligent::COMPARISON_FUNC_GREATER;
case GL_EQUAL: return Diligent::COMPARISON_FUNC_EQUAL;
case GL_NOTEQUAL: return Diligent::COMPARISON_FUNC_NOT_EQUAL;
case GL_ALWAYS: return Diligent::COMPARISON_FUNC_ALWAYS;
case GL_NEVER: return Diligent::COMPARISON_FUNC_NEVER;
default:
MG_Util::Debug::LogE("%s: not handled param: %s", __func__, MG_Util::Debug::GLEnumToString(param));
return Diligent::COMPARISON_FUNC_NEVER;
}
}
Diligent::TEXTURE_ADDRESS_MODE ConvertAddressMode(GLint param) {
switch (param) {
case GL_REPEAT: return Diligent::TEXTURE_ADDRESS_WRAP;
case GL_CLAMP_TO_EDGE: return Diligent::TEXTURE_ADDRESS_CLAMP;
case GL_MIRRORED_REPEAT: return Diligent::TEXTURE_ADDRESS_MIRROR;
default:
MG_Util::Debug::LogE("%s: not handled param: %s", __func__, MG_Util::Debug::GLEnumToString(param));
return Diligent::TEXTURE_ADDRESS_WRAP;
}
}
void ActiveTexture(GLenum texture) { void ActiveTexture(GLenum texture) {
MG_Util::Debug::LogD("glActiveTexture, texture: %d", texture); MG_Util::Debug::LogD("glActiveTexture, texture: %d", texture);
GLenum result = MG_State::BindTextureUnit(texture); GLenum result = MG_State::BindTextureUnit(texture);
@@ -17,8 +195,9 @@ namespace MG_GL::GL {
void BindTexture(GLenum target, GLuint texture) { void BindTexture(GLenum target, GLuint texture) {
MG_Util::Debug::LogD("glBindTexture, target: %d, texture: %d", target, texture); MG_Util::Debug::LogD("glBindTexture, target: %d, texture: %d", target, texture);
GLenum result = MG_State::BindTexture(target, texture); GLenum result = MG_State::BindTexture(target, texture);
if (result == GL_NO_ERROR) if (result == GL_NO_ERROR) {
return; return;
}
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
} }
@@ -26,8 +205,27 @@ namespace MG_GL::GL {
void DeleteTextures(GLsizei n, const GLuint* textures) { void DeleteTextures(GLsizei n, const GLuint* textures) {
MG_Util::Debug::LogD("glDeleteTextures, n: %d, textures: %p", n, textures); MG_Util::Debug::LogD("glDeleteTextures, n: %d, textures: %p", n, textures);
GLenum result = MG_State::DeleteTextures(n, textures); GLenum result = MG_State::DeleteTextures(n, textures);
if (result == GL_NO_ERROR) if (result == GL_NO_ERROR) {
for (GLsizei i = 0; i < n; ++i) {
GLuint tex = textures[i];
auto texIt = MG_Diligent::g_TextureMap.find(tex);
if (texIt != MG_Diligent::g_TextureMap.end()) {
if (texIt->second) {
texIt->second->Release();
}
MG_Diligent::g_TextureMap.erase(texIt);
}
auto srvIt = MG_Diligent::g_TextureViewMap.find(tex);
if (srvIt != MG_Diligent::g_TextureViewMap.end()) {
if (srvIt->second) {
srvIt->second->Release();
}
MG_Diligent::g_TextureViewMap.erase(srvIt);
}
}
return; return;
}
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
} }
@@ -35,52 +233,453 @@ namespace MG_GL::GL {
void GenTextures(GLsizei n, GLuint* textures) { void GenTextures(GLsizei n, GLuint* textures) {
MG_Util::Debug::LogD("glGenTextures, n: %d, textures: %p", n, textures); MG_Util::Debug::LogD("glGenTextures, n: %d, textures: %p", n, textures);
GLenum result = MG_State::CreateTextures(n, textures); GLenum result = MG_State::CreateTextures(n, textures);
if (result == GL_NO_ERROR) if (result == GL_NO_ERROR) {
for (GLsizei i = 0; i < n; ++i) {
MG_Diligent::g_TextureMap[textures[i]] = nullptr;
MG_Diligent::g_TextureViewMap[textures[i]] = nullptr;
}
return; return;
}
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
} }
void TexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, Diligent::Uint32 CalculateMipLevels(GLsizei width, GLsizei height) {
Diligent::Uint32 levels = 1;
GLsizei size = std::max(width, height);
while (size > 1) {
size >>= 1;
levels++;
}
return levels;
}
void TexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border,
GLenum format, GLenum type, const void* data) { GLenum format, GLenum type, const void* data) {
MG_Util::Debug::LogD("glTexImage2D, target: %d, level: %d, internalFormat: %d, width: %d, height: %d, format: %d, type: %d, data: %p", MG_Util::Debug::LogD("glTexImage2D, target: %d, level: %d, internalFormat: %d, width: %d, height: %d, format: %d, type: %d, data: %p",
target, level, internalFormat, width, height, format, type, data); target, level, internalFormat, width, height, format, type, data);
GLenum result = MG_State::UploadTexture2D(target, level, internalFormat, width, height, border, format, type, data);
if (result == GL_NO_ERROR) GLenum result = MG_State::UploadTexture2D(target, level, internalFormat, width, height,
border, format, type, data);
if (result != GL_NO_ERROR) {
MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
return; return;
MG_State::SetError(result); }
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
MG_Util::Debug::LogD("TexImage2D: MG_State::UploadTexture2D successful.");
auto& texState = *MG_State_T::textureState;
auto activeUnit = texState.activeTextureUnit_;
auto unitState = &texState.textureUnits_[activeUnit];
GLuint boundTextureID = unitState->GetBoundTexture(target);
if (boundTextureID == 0) {
MG_Util::Debug::LogD("TexImage2D: No texture bound to active unit. Returning.");
return;
}
Diligent::ITexture* pTexture = nullptr;
Diligent::ITextureView* pSRV = nullptr;
auto texIt = MG_Diligent::g_TextureMap.find(boundTextureID);
if (texIt != MG_Diligent::g_TextureMap.end()) {
pTexture = texIt->second;
}
auto srvIt = MG_Diligent::g_TextureViewMap.find(boundTextureID);
if (srvIt != MG_Diligent::g_TextureViewMap.end()) {
pSRV = srvIt->second;
}
Diligent::TEXTURE_FORMAT newFormat = ConvertInternalFormat(internalFormat);
MG_Util::Debug::LogD("TexImage2D: New internalFormat: %d maps to Diligent format: %d",
internalFormat, newFormat);
bool needCreateTexture = false;
bool isBaseLevel = (level == 0);
if (!pTexture) {
MG_Util::Debug::LogD("TexImage2D: No existing Diligent texture found for GL name %u. Creating new.", boundTextureID);
needCreateTexture = true;
} else {
Diligent::TextureDesc existingDesc = pTexture->GetDesc();
if (isBaseLevel &&
(existingDesc.Width != static_cast<Diligent::Uint32>(width) ||
existingDesc.Height != static_cast<Diligent::Uint32>(height) ||
existingDesc.Format != newFormat)) {
MG_Util::Debug::LogD("TexImage2D: Base level properties changed. Recreating texture.");
MG_Util::Debug::LogD("TexImage2D: Old (W:%u, H:%u, F:%d), New (W:%d, H:%d, F:%d)",
existingDesc.Width, existingDesc.Height, existingDesc.Format,
width, height, newFormat);
needCreateTexture = true;
} else if (level >= static_cast<GLint>(existingDesc.MipLevels)) {
MG_Util::Debug::LogD("TexImage2D: Level %d exceeds current mip levels (%d). Recreating texture.",
level, existingDesc.MipLevels);
needCreateTexture = true;
}
}
if (needCreateTexture) {
if (pSRV) {
MG_Util::Debug::LogD("TexImage2D: Releasing existing SRV %p", (void*)pSRV);
pSRV->Release();
MG_Diligent::g_TextureViewMap[boundTextureID] = nullptr;
pSRV = nullptr;
}
if (pTexture) {
MG_Util::Debug::LogD("TexImage2D: Releasing existing texture %p", (void*)pTexture);
pTexture->Release();
MG_Diligent::g_TextureMap[boundTextureID] = nullptr;
pTexture = nullptr;
}
Diligent::Uint32 mipLevels = 1;
if (isBaseLevel) {
mipLevels = CalculateMipLevels(width, height);
} else if (pTexture) {
mipLevels = pTexture->GetDesc().MipLevels;
}
Diligent::TextureDesc TexDesc;
if constexpr (MG_Global::Common::LogLevel <= MG_Constants::Common::LOG_LEVEL_DEBUG) {
TexDesc.Name = std::format("GL Texture {}", boundTextureID).c_str();
}
TexDesc.Type = Diligent::RESOURCE_DIM_TEX_2D;
TexDesc.Width = width;
TexDesc.Height = height;
TexDesc.Format = newFormat;
TexDesc.MipLevels = mipLevels;
bool isDepthStencil = false;
switch (internalFormat) {
case GL_DEPTH_COMPONENT:
case GL_DEPTH_COMPONENT16:
case GL_DEPTH_COMPONENT24:
case GL_DEPTH_COMPONENT32:
case GL_DEPTH_COMPONENT32F:
case GL_DEPTH_STENCIL:
case GL_DEPTH24_STENCIL8:
case GL_DEPTH32F_STENCIL8:
isDepthStencil = true;
break;
default:
isDepthStencil = false;
}
if (isDepthStencil) {
TexDesc.BindFlags = Diligent::BIND_SHADER_RESOURCE | Diligent::BIND_DEPTH_STENCIL;
} else {
TexDesc.BindFlags = Diligent::BIND_SHADER_RESOURCE | Diligent::BIND_RENDER_TARGET;
}
MG_Util::Debug::LogD("TexImage2D: Creating new Diligent texture with Width: %d, Height: %d, Format: %d, MipLevels: %u",
width, height, newFormat, mipLevels);
Diligent::ITexture* newTexture = nullptr;
MG_Diligent::g_pDevice->CreateTexture(TexDesc, nullptr, &newTexture);
if (newTexture) {
MG_Util::Debug::LogD("TexImage2D: Created new Diligent texture %p for GL name %u.",
(void*)newTexture, boundTextureID);
Diligent::TextureViewDesc SRVDesc;
SRVDesc.ViewType = Diligent::TEXTURE_VIEW_SHADER_RESOURCE;
SRVDesc.TextureDim = Diligent::RESOURCE_DIM_TEX_2D;
SRVDesc.MostDetailedMip = 0;
SRVDesc.NumMipLevels = TexDesc.MipLevels;
Diligent::ITextureView* newSRV = nullptr;
newTexture->CreateView(SRVDesc, &newSRV);
MG_Util::Debug::LogD("TexImage2D: Created new SRV %p for texture.", (void*)newSRV);
MG_Diligent::g_TextureMap[boundTextureID] = newTexture;
MG_Diligent::g_TextureViewMap[boundTextureID] = newSRV;
pTexture = newTexture;
pSRV = newSRV;
} else {
MG_Util::Debug::LogE("TexImage2D: Failed to create new texture!");
return;
}
}
if (pTexture && data) {
Diligent::TextureSubResData SubResData;
SubResData.pData = data;
SubResData.Stride = width * GetBytesPerPixel(format, type);
Diligent::Box UpdateBox;
UpdateBox.MinX = 0;
UpdateBox.MaxX = width;
UpdateBox.MinY = 0;
UpdateBox.MaxY = height;
UpdateBox.MinZ = 0;
UpdateBox.MaxZ = 1;
MG_Util::Debug::LogD("TexImage2D: Updating texture. Level: %d, Box: [%u,%u]x[%u,%u], Stride: %llu",
level, UpdateBox.MinX, UpdateBox.MaxX, UpdateBox.MinY, UpdateBox.MaxY, SubResData.Stride);
MG_Diligent::g_pContext->UpdateTexture(
pTexture,
level,
0,
UpdateBox,
SubResData,
Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION,
Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION
);
MG_Util::Debug::LogD("TexImage2D: UpdateTexture completed for level %d.", level);
}
} }
void TexParameterf(GLenum target, GLenum pname, GLfloat param) { void TexParameterf(GLenum target, GLenum pname, GLfloat param) {
MG_Util::Debug::LogD("glTexParameterf, target: %d, pname: %d, param: %f", target, pname, param); MG_Util::Debug::LogD("glTexParameterf, target: %d, pname: %d, param: %f", target, pname, param);
GLenum result = MG_State::SetTexturePropertyFloat(target, pname, param); GLenum result = MG_State::SetTexturePropertyFloat(target, pname, param);
if (result == GL_NO_ERROR) if (result == GL_NO_ERROR) {
MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
return; return;
MG_State::SetError(result); }
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
// TODO: Fix sampler
auto& texState = *MG_State_T::textureState;
auto activeUnit = texState.activeTextureUnit_;
auto unitState = &texState.textureUnits_[activeUnit];
GLuint boundTextureID = unitState->GetBoundTexture(target);
if (boundTextureID == 0) {
MG_Util::Debug::LogD("TexParameterf: No texture bound. Skipping sampler update.");
return;
}
Diligent::SamplerDesc SamDesc;
auto it = MG_Diligent::g_SamplerMap.find(boundTextureID);
if (it != MG_Diligent::g_SamplerMap.end() && it->second) {
SamDesc = it->second->GetDesc();
} else {
SamDesc.MinFilter = Diligent::FILTER_TYPE_LINEAR;
SamDesc.MagFilter = Diligent::FILTER_TYPE_LINEAR;
SamDesc.AddressU = Diligent::TEXTURE_ADDRESS_WRAP;
SamDesc.AddressV = Diligent::TEXTURE_ADDRESS_WRAP;
SamDesc.AddressW = Diligent::TEXTURE_ADDRESS_WRAP;
}
switch (pname) {
case GL_TEXTURE_MIN_FILTER:
FillFilterTypeFromGLEnum(pname, param, SamDesc.MinFilter, SamDesc.MagFilter, SamDesc.MipFilter);
break;
case GL_TEXTURE_MAG_FILTER:
FillFilterTypeFromGLEnum(pname, param, SamDesc.MinFilter, SamDesc.MagFilter, SamDesc.MipFilter);
break;
case GL_TEXTURE_WRAP_S:
SamDesc.AddressU = ConvertAddressMode(param);
break;
case GL_TEXTURE_WRAP_T:
SamDesc.AddressV = ConvertAddressMode(param);
break;
case GL_TEXTURE_WRAP_R:
SamDesc.AddressW = ConvertAddressMode(param);
break;
case GL_TEXTURE_MIN_LOD:
SamDesc.MinLOD = (float)param;
break;
case GL_TEXTURE_MAX_LOD:
SamDesc.MaxLOD = param;
break;
case GL_TEXTURE_COMPARE_FUNC:
SamDesc.ComparisonFunc = ConvertComparsionFunc(param);
break;
case GL_TEXTURE_COMPARE_MODE:
FillFilterTypeFromGLEnum(pname, param, SamDesc.MinFilter, SamDesc.MagFilter, SamDesc.MipFilter);
break;
default:
MG_Util::Debug::LogE("%s: not handled pname: %s", __func__, MG_Util::Debug::GLEnumToString(pname));
}
Diligent::ISampler* pNewSampler = nullptr;
MG_Diligent::g_pDevice->CreateSampler(SamDesc, &pNewSampler);
if (it != MG_Diligent::g_SamplerMap.end()) {
if (it->second) {
it->second->Release();
}
it->second = pNewSampler;
} else {
MG_Diligent::g_SamplerMap[boundTextureID] = pNewSampler;
}
MG_Util::Debug::LogD("TexParameterf: Updated sampler for texture %u", boundTextureID);
} }
void TexParameteri(GLenum target, GLenum pname, GLint param) { void TexParameteri(GLenum target, GLenum pname, GLint param) {
MG_Util::Debug::LogD("glTexParameteri, target: %d, pname: %d, param: %d", target, pname, param); MG_Util::Debug::LogD("glTexParameteri, target: %d, pname: %d, param: %d", target, pname, param);
GLenum result = MG_State::SetTexturePropertyInt(target, pname, param); GLenum result = MG_State::SetTexturePropertyInt(target, pname, param);
if (result == GL_NO_ERROR) if (result != GL_NO_ERROR) {
MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
return; return;
MG_State::SetError(result); }
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
// TODO: Fix sampler
auto& texState = *MG_State_T::textureState;
auto activeUnit = texState.activeTextureUnit_;
auto unitState = &texState.textureUnits_[activeUnit];
GLuint boundTextureID = unitState->GetBoundTexture(target);
if (boundTextureID == 0) {
MG_Util::Debug::LogD("TexParameteri: No texture bound. Skipping sampler update.");
return;
}
Diligent::SamplerDesc SamDesc;
auto it = MG_Diligent::g_SamplerMap.find(boundTextureID);
if (it != MG_Diligent::g_SamplerMap.end() && it->second) {
SamDesc = it->second->GetDesc();
} else {
SamDesc.MinFilter = Diligent::FILTER_TYPE_LINEAR;
SamDesc.MagFilter = Diligent::FILTER_TYPE_LINEAR;
SamDesc.AddressU = Diligent::TEXTURE_ADDRESS_WRAP;
SamDesc.AddressV = Diligent::TEXTURE_ADDRESS_WRAP;
SamDesc.AddressW = Diligent::TEXTURE_ADDRESS_WRAP;
}
switch (pname) {
case GL_TEXTURE_MIN_FILTER:
FillFilterTypeFromGLEnum(pname, param, SamDesc.MinFilter, SamDesc.MagFilter, SamDesc.MipFilter);
break;
case GL_TEXTURE_MAG_FILTER:
FillFilterTypeFromGLEnum(pname, param, SamDesc.MagFilter, SamDesc.MagFilter, SamDesc.MipFilter);
break;
case GL_TEXTURE_WRAP_S:
SamDesc.AddressU = ConvertAddressMode(param);
break;
case GL_TEXTURE_WRAP_T:
SamDesc.AddressV = ConvertAddressMode(param);
break;
case GL_TEXTURE_WRAP_R:
SamDesc.AddressW = ConvertAddressMode(param);
break;
case GL_TEXTURE_MIN_LOD:
SamDesc.MinLOD = (float)param;
break;
case GL_TEXTURE_MAX_LOD:
SamDesc.MaxLOD = (float)param;
break;
case GL_TEXTURE_COMPARE_FUNC:
SamDesc.ComparisonFunc = ConvertComparsionFunc(param);
break;
case GL_TEXTURE_COMPARE_MODE:
FillFilterTypeFromGLEnum(pname, param, SamDesc.MinFilter, SamDesc.MagFilter, SamDesc.MipFilter);
break;
default:
MG_Util::Debug::LogE("%s: not handled pname: %s", __func__, MG_Util::Debug::GLEnumToString(pname));
}
Diligent::ISampler* pNewSampler = nullptr;
MG_Diligent::g_pDevice->CreateSampler(SamDesc, &pNewSampler);
if (it != MG_Diligent::g_SamplerMap.end()) {
if (it->second) {
it->second->Release();
}
it->second = pNewSampler;
} else {
MG_Diligent::g_SamplerMap[boundTextureID] = pNewSampler;
}
MG_Util::Debug::LogD("TexParameteri: Updated sampler for texture %u", boundTextureID);
} }
void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
GLsizei height, GLenum format, GLenum type, const void* pixels) { GLsizei height, GLenum format, GLenum type, const void* pixels) {
MG_Util::Debug::LogD("glTexSubImage2D, target: %d, level: %d, xoffset: %d, yoffset: %d, width: %d, height: %d, format: %d, type: %d, pixels: %p", MG_Util::Debug::LogD("glTexSubImage2D, target: %d, level: %d, xoffset: %d, yoffset: %d, width: %d, height: %d, format: %d, type: %d, pixels: %p",
target, level, xoffset, yoffset, width, height, format, type, pixels); target, level, xoffset, yoffset, width, height, format, type, pixels);
GLenum result = MG_State::UpdateTextureRegion2D(target, level, xoffset, yoffset, width, height, format, type, pixels); GLenum result = MG_State::UpdateTextureRegion2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
if (result == GL_NO_ERROR) if (result != GL_NO_ERROR) {
MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
return; return;
MG_State::SetError(result); }
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
auto& texState = *MG_State_T::textureState;
auto activeUnit = texState.activeTextureUnit_;
auto unitState = &texState.textureUnits_[activeUnit];
GLuint boundTextureID = unitState->GetBoundTexture(target);
MG_Util::Debug::LogD("TexSubImage2D: bound texture: GL name %u", boundTextureID);
if (boundTextureID == 0) {
MG_Util::Debug::LogD("TexSubImage2D: No texture bound to active unit. Skipping update.");
return;
}
Diligent::ITexture* pTexture = nullptr;
auto texIt = MG_Diligent::g_TextureMap.find(boundTextureID);
if (texIt != MG_Diligent::g_TextureMap.end()) {
pTexture = texIt->second;
}
if (!pTexture) {
MG_Util::Debug::LogW("TexSubImage2D: Diligent texture not found for GL name %u", boundTextureID);
return;
}
const auto& texDesc = pTexture->GetDesc();
if (!(texDesc.BindFlags & Diligent::BIND_SHADER_RESOURCE)) {
MG_Util::Debug::LogE("TexSubImage2D: Texture %u does not have BIND_SHADER_RESOURCE flag", boundTextureID);
return;
}
auto rowLength = MG_State::QueryPixelStoreInt(GL_UNPACK_ROW_LENGTH);
rowLength = ((rowLength > 0) ? rowLength : width);
auto skipRows = MG_State::QueryPixelStoreInt(GL_UNPACK_SKIP_ROWS);
auto skipPixels = MG_State::QueryPixelStoreInt(GL_UNPACK_SKIP_PIXELS);
auto bpp = GetBytesPerPixel(format, type);
char* pixelStart = (char*)pixels + bpp * (rowLength * skipRows + skipPixels);
Diligent::TextureSubResData SubResData;
SubResData.Stride = rowLength * bpp;
SubResData.pData = pixelStart;
Diligent::Box UpdateBox;
UpdateBox.MinX = xoffset;
UpdateBox.MaxX = xoffset + width;
UpdateBox.MinY = yoffset;
UpdateBox.MaxY = yoffset + height;
UpdateBox.MinZ = 0;
UpdateBox.MaxZ = 1;
MG_Util::Debug::LogD("TexSubImage2D: Got GL_UNPACK_ROW_LENGTH = %d", rowLength);
MG_Util::Debug::LogD("TexSubImage2D: Updating region [%d,%d]-[%d,%d] at level %d, %d bytes",
xoffset, yoffset, xoffset+width, yoffset+height, level, width * height * GetBytesPerPixel(format, type));
// if (MG_Diligent::IsInRenderPass) {
// MG_Diligent::g_pContext->EndRenderPass();
// MG_Diligent::IsInRenderPass = false;
// }
MG_Diligent::g_pContext->UpdateTexture(
pTexture,
level,
0,
UpdateBox,
SubResData,
Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION,
Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION
);
MG_Util::Debug::LogD("TexSubImage2D: Update completed successfully");
} }
void GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* params) { void GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* params) {
MG_Util::Debug::LogD("glGetTexLevelParameteriv, target: %d, level: %d, pname: %d, params: %p", MG_Util::Debug::LogD("glGetTexLevelParameteriv, target: %d, level: %d, pname: %d, params: %p",
target, level, pname, params); target, level, pname, params);
@@ -90,4 +689,10 @@ namespace MG_GL::GL {
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
} }
}
void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
MG_Util::Debug::LogD("glCopyTexSubImage2D, target: %d, level: %d, xoffset: %d, yoffset: %d, x: %d, y: %d, width: %d, height: %d",
target, level, xoffset, yoffset, x, y, width, height);
}
}
@@ -5,8 +5,6 @@
#ifndef MOBILEGL_GL_TEXTURE_H #ifndef MOBILEGL_GL_TEXTURE_H
#define MOBILEGL_GL_TEXTURE_H #define MOBILEGL_GL_TEXTURE_H
#include "../../../../Includes.h"
namespace MG_GL::GL { namespace MG_GL::GL {
void ActiveTexture(GLenum texture); void ActiveTexture(GLenum texture);
void BindTexture(GLenum target, GLuint texture); void BindTexture(GLenum target, GLuint texture);
@@ -17,6 +15,7 @@ namespace MG_GL::GL {
void TexParameteri(GLenum target, GLenum pname, GLint param); void TexParameteri(GLenum target, GLenum pname, GLint param);
void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels); void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels);
void GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* params); void GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* params);
void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
} }
#endif //MOBILEGL_GL_TEXTURE_H #endif //MOBILEGL_GL_TEXTURE_H
@@ -2,13 +2,15 @@
// Created by BZLZHH on 2025/3/15. // Created by BZLZHH on 2025/3/15.
// //
#include "GL_VertexArray.h" #include "../../../../Includes.h"
namespace MG_GL::GL { namespace MG_GL::GL {
void GenVertexArrays(GLsizei n, GLuint* arrays) { void GenVertexArrays(GLsizei n, GLuint* arrays) {
MG_Util::Debug::LogD("glGenVertexArrays, n: %d, arrays: %p", n, arrays); MG_Util::Debug::LogD("glGenVertexArrays, n: %d, arrays: %p", n, arrays);
GLenum result = MG_State::GenVertexArraysNames(n, arrays); GLenum result = MG_State::GenVertexArraysNames(n, arrays);
if (result == GL_NO_ERROR) return; if (result == GL_NO_ERROR) {
return;
}
MG_State::SetError(result); MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result)); MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
} }
@@ -5,8 +5,6 @@
#ifndef MOBILEGL_GL_VERTEXARRAY_H #ifndef MOBILEGL_GL_VERTEXARRAY_H
#define MOBILEGL_GL_VERTEXARRAY_H #define MOBILEGL_GL_VERTEXARRAY_H
#include "../../../../Includes.h"
namespace MG_GL::GL { namespace MG_GL::GL {
void GenVertexArrays(GLsizei n, GLuint* arrays); void GenVertexArrays(GLsizei n, GLuint* arrays);
void BindVertexArray(GLuint array); void BindVertexArray(GLuint array);
@@ -2,7 +2,7 @@
// Created by Swung 0x48 on 2025/6/20. // Created by Swung 0x48 on 2025/6/20.
// //
#include "GLXFuncsDefinitions.h" #include "../../../../Includes.h"
MG_EXPORT void* glXGetProcAddress(const char *name) { MG_EXPORT void* glXGetProcAddress(const char *name) {
return MG_GL::GLX::GetProcAddress(name); return MG_GL::GLX::GetProcAddress(name);
@@ -5,6 +5,4 @@
#ifndef MOBILEGL_GLX_FUNCS_DEFINITIONS_H #ifndef MOBILEGL_GLX_FUNCS_DEFINITIONS_H
#define MOBILEGL_GLX_FUNCS_DEFINITIONS_H #define MOBILEGL_GLX_FUNCS_DEFINITIONS_H
#include "../../../../Includes.h"
#endif //MOBILEGL_GLX_FUNCS_DEFINITIONS_H #endif //MOBILEGL_GLX_FUNCS_DEFINITIONS_H
+72 -55
View File
@@ -4,38 +4,33 @@
// TODO: Add more gl error check for buffer state manager. // TODO: Add more gl error check for buffer state manager.
#include "BufferState.h" #include "../../../Includes.h"
GLenum BufferState::GenName(GLuint *buffer) { //GLenum BufferState::GenName(GLuint *buffer) {
MG_Util::Debug::LogD("MG_State: Buffer: GenName"); // MG_Util::Debug::LogD("MG_State: Buffer: GenName");
if (!buffer) // if (!buffer)
return GL_INVALID_VALUE; // return GL_INVALID_VALUE;
//
GLuint id = 0; // GLuint id = 0;
if (freeId_.empty()) { // if (freeId_.empty()) {
id = lastId_++; // id = lastId_++;
} else { // } else {
id = freeId_.back(); // id = freeId_.back();
freeId_.pop_back(); // freeId_.pop_back();
} // }
//
*buffer = id; // *buffer = id;
MG_Util::Debug::LogD("MG_State: Buffer: Gen new name %d", id); // MG_Util::Debug::LogD("MG_State: Buffer: Gen new name %d", id);
//
return GL_NO_ERROR; // return GL_NO_ERROR;
} //}
GLenum BufferState::GenNameN(GLsizei n, GLuint* buffers) { GLenum BufferState::GenNameN(GLsizei n, GLuint* buffers) {
MG_Util::Debug::LogD("MG_State: Buffer: GenNameN called with n=%d", n); MG_Util::Debug::LogD("MG_State: Buffer: GenNameN called with n=%d", n);
if (n < 0) return GL_INVALID_VALUE; if (n < 0 || buffers == nullptr) return GL_INVALID_VALUE;
indexGenerator_.Generate(n, buffers);
for (GLsizei i = 0; i < n; ++i) {
GLenum result = GenName(&buffers[i]);
if (result != GL_NO_ERROR) {
MG_Util::Debug::LogE("MG_State: Buffer: GenNameN failed with error 0x%x", result);
return result;
}
}
MG_Util::Debug::LogD("MG_State: Buffer: GenNameN created buffers successfully"); MG_Util::Debug::LogD("MG_State: Buffer: GenNameN created buffers successfully");
return GL_NO_ERROR; return GL_NO_ERROR;
} }
@@ -48,7 +43,14 @@ GLenum BufferState::Create(GLuint buffer) {
if (ValidateAllocatedHandle(buffer)) if (ValidateAllocatedHandle(buffer))
return GL_INVALID_VALUE; return GL_INVALID_VALUE;
BufferObject& obj = buffers_[buffer]; if (bufferObjects_.size() <= buffer) {
bufferObjects_.resize(buffer + 1);
}
if (bufferObjects_[buffer] == nullptr) {
bufferObjects_[buffer] = std::make_unique<BufferObject>();
}
BufferObject& obj = *GetBufferObject(buffer);
MG_Util::Debug::LogD("MG_State: Buffer: Create created buffer %d", buffer); MG_Util::Debug::LogD("MG_State: Buffer: Create created buffer %d", buffer);
obj.generated = true; obj.generated = true;
obj.dirty = true; obj.dirty = true;
@@ -71,9 +73,12 @@ GLenum BufferState::CommitStorage(GLenum target, GLsizeiptr size, const void* da
if (it == currentBindings_.end() || it->second == 0) if (it == currentBindings_.end() || it->second == 0)
return GL_INVALID_OPERATION; return GL_INVALID_OPERATION;
BufferObject& obj = buffers_[it->second]; BufferObject& obj = *GetBufferObject(it->second);
MG_Util::Debug::LogD("MG_State: Buffer: CommitStorage get buffer object %u at target 0x%x",it->second,target); MG_Util::Debug::LogD("MG_State: Buffer: CommitStorage get buffer object %u at target 0x%x",it->second,target);
obj.usage = usage; obj.usage = usage;
obj.isDynamic = (usage == GL_DYNAMIC_DRAW || usage == GL_DYNAMIC_READ ||
usage == GL_DYNAMIC_COPY || usage == GL_STREAM_DRAW);
obj.data.reserve(std::bit_ceil((size_t)size));
obj.data.resize(size); obj.data.resize(size);
if (data) { if (data) {
memcpy(obj.data.data(), data, size); memcpy(obj.data.data(), data, size);
@@ -94,7 +99,7 @@ GLenum BufferState::CommitStorageRegion(GLenum target, GLintptr offset, GLsizeip
if (it == currentBindings_.end() || it->second == 0) if (it == currentBindings_.end() || it->second == 0)
return GL_INVALID_OPERATION; return GL_INVALID_OPERATION;
BufferObject& obj = buffers_[it->second]; BufferObject& obj = *GetBufferObject(it->second);
MG_Util::Debug::LogD("MG_State: Buffer: BufferSubData get buffer object %u at target 0x%x", it->second, target); MG_Util::Debug::LogD("MG_State: Buffer: BufferSubData get buffer object %u at target 0x%x", it->second, target);
if (static_cast<size_t>(offset + size) > obj.data.size()) return GL_INVALID_VALUE; if (static_cast<size_t>(offset + size) > obj.data.size()) return GL_INVALID_VALUE;
@@ -123,7 +128,7 @@ GLenum BufferState::AcquireBufferMemoryRange(GLenum target, GLintptr offset, GLs
return GL_INVALID_OPERATION; return GL_INVALID_OPERATION;
} }
BufferObject& obj = buffers_[it->second]; BufferObject& obj = *GetBufferObject(it->second);
MG_Util::Debug::LogD("MG_State: Buffer: AcquireBufferMemoryRange operating on buffer %u", it->second); MG_Util::Debug::LogD("MG_State: Buffer: AcquireBufferMemoryRange operating on buffer %u", it->second);
if (obj.isMapped) { if (obj.isMapped) {
MG_Util::Debug::LogE("MG_State: Buffer: AcquireBufferMemoryRange failed: buffer %u is already mapped", it->second); MG_Util::Debug::LogE("MG_State: Buffer: AcquireBufferMemoryRange failed: buffer %u is already mapped", it->second);
@@ -159,7 +164,7 @@ GLenum BufferState::SyncBufferMemory(GLenum target, GLintptr offset, GLsizeiptr
if (it == currentBindings_.end() || it->second == 0) if (it == currentBindings_.end() || it->second == 0)
return GL_INVALID_OPERATION; return GL_INVALID_OPERATION;
BufferObject& obj = buffers_[it->second]; BufferObject& obj = *GetBufferObject(it->second);
if (!obj.isMapped || !(obj.mapAccessFlags & GL_MAP_FLUSH_EXPLICIT_BIT)) if (!obj.isMapped || !(obj.mapAccessFlags & GL_MAP_FLUSH_EXPLICIT_BIT))
return GL_INVALID_OPERATION; return GL_INVALID_OPERATION;
@@ -183,8 +188,8 @@ GLenum BufferState::CopyBufferRange(GLenum readTarget, GLenum writeTarget, GLint
if (readBuffer == 0 || writeBuffer == 0 || readBuffer == writeBuffer) if (readBuffer == 0 || writeBuffer == 0 || readBuffer == writeBuffer)
return GL_INVALID_OPERATION; return GL_INVALID_OPERATION;
BufferObject& src = buffers_[readBuffer]; BufferObject& src = *GetBufferObject(readBuffer);
BufferObject& dst = buffers_[writeBuffer]; BufferObject& dst = *GetBufferObject(writeBuffer);
if (static_cast<size_t>(readOffset + size) > src.data.size() || if (static_cast<size_t>(readOffset + size) > src.data.size() ||
static_cast<size_t>(writeOffset + size) > dst.data.size()) static_cast<size_t>(writeOffset + size) > dst.data.size())
@@ -204,7 +209,7 @@ GLenum BufferState::AcquireBufferMemory(GLenum target, GLenum access, void** map
default: default:
flags = access; flags = access;
} }
return AcquireBufferMemoryRange(target, 0, buffers_[currentBindings_[target]].data.size(), flags, mappedPointer); return AcquireBufferMemoryRange(target, 0, GetBufferObject(currentBindings_[target])->data.size(), flags, mappedPointer);
} }
GLenum BufferState::ReleaseBufferMemory(GLenum target) { GLenum BufferState::ReleaseBufferMemory(GLenum target) {
@@ -215,7 +220,7 @@ GLenum BufferState::ReleaseBufferMemory(GLenum target) {
if (it == currentBindings_.end() || it->second == 0) if (it == currentBindings_.end() || it->second == 0)
return GL_INVALID_OPERATION; return GL_INVALID_OPERATION;
BufferObject& obj = buffers_[it->second]; BufferObject& obj = *GetBufferObject(it->second);
if (!obj.isMapped) if (!obj.isMapped)
return GL_INVALID_OPERATION; return GL_INVALID_OPERATION;
@@ -232,28 +237,28 @@ GLenum BufferState::ReleaseBufferMemory(GLenum target) {
return GL_NO_ERROR; return GL_NO_ERROR;
} }
bool BufferState::ValidateAllocatedHandle(GLuint buffer) { bool BufferState::ValidateAllocatedHandle(GLuint buffer) const {
bool isValid = buffers_.find(buffer) != buffers_.end(); bool isValid = buffer != 0 && bufferObjects_.size() > buffer && bufferObjects_[buffer] != nullptr;
MG_Util::Debug::LogD("MG_State: Buffer: ValidateAllocatedHandle called on buffer %u returns %d", buffer, isValid); MG_Util::Debug::LogD("MG_State: Buffer: ValidateAllocatedHandle called on buffer %u returns %d", buffer, isValid);
return isValid; return isValid;
} }
bool BufferState::ValidateGeneratedName(GLuint buffer) { bool BufferState::ValidateGeneratedName(GLuint buffer) const {
bool inFreeList = std::find(freeId_.begin(), freeId_.end(), buffer) != freeId_.end(); bool isValid = indexGenerator_.IsValid(buffer);
bool lessThanLast = buffer < lastId_; // lastId_ is not generated yet MG_Util::Debug::LogD("MG_State: Buffer: ValidateGeneratedName called on buffer %u returns %s", buffer, isValid ? "true" : "false");
MG_Util::Debug::LogD("MG_State: Buffer: ValidateGeneratedName called on buffer %u returns %d", buffer, lessThanLast && !inFreeList); return isValid;
return lessThanLast && !inFreeList;
} }
void BufferState::Delete(GLuint buffer) { void BufferState::Delete(GLuint buffer) {
buffers_.erase(buffer); MG_Util::Debug::LogD("MG_State: Buffer: Delete buffer %u", buffer);
if (ValidateGeneratedName(buffer)) if (bufferObjects_.size() > buffer)
// TODO: Prevent the object that uses a freeId from conflicting with legacy object in the backend. bufferObjects_[buffer].reset();
//freeId_.emplace_back(buffer); indexGenerator_.Delete(buffer);
for (auto& [target, id] : currentBindings_) { for (auto& [target, id] : currentBindings_) {
if (id == buffer) id = 0; if (id == buffer) id = 0;
} }
MG_Util::Debug::LogD("MG_State: Buffer: Delete buffer %u", buffer); MG_Util::Debug::LogD("MG_State: Buffer: Delete buffer %u successfully", buffer);
} }
GLenum BufferState::DeleteN(GLsizei n, const GLuint* buffers) { GLenum BufferState::DeleteN(GLsizei n, const GLuint* buffers) {
@@ -268,8 +273,9 @@ GLenum BufferState::DeleteN(GLsizei n, const GLuint* buffers) {
} }
bool BufferState::IsValidTarget_(GLenum target) { bool BufferState::IsValidTarget_(GLenum target) {
MG_Util::Debug::LogD("MG_State: Buffer: IsValidTarget_ called with target=0x%x,result=%d", target, !(MG_Constants::Buffer::VALID_TARGETS.find(target) == MG_Constants::Buffer::VALID_TARGETS.end())); bool ret = MG_Constants::Common::Contains(target, MG_Constants::Buffer::VALID_TARGETS);
return !(MG_Constants::Buffer::VALID_TARGETS.find(target) == MG_Constants::Buffer::VALID_TARGETS.end()); MG_Util::Debug::LogD("MG_State: Buffer: IsValidTarget_ called with target=0x%x,result=%d", target, ret);
return ret;
} }
GLenum BufferState::QueryPropertyIntVector(GLenum target, GLenum pname, GLint* params) const { GLenum BufferState::QueryPropertyIntVector(GLenum target, GLenum pname, GLint* params) const {
@@ -282,7 +288,7 @@ GLenum BufferState::QueryPropertyIntVector(GLenum target, GLenum pname, GLint* p
return GL_INVALID_ENUM; return GL_INVALID_ENUM;
} }
if (MG_Constants::Buffer::VALID_PARAM_NAMES.find(pname) == MG_Constants::Buffer::VALID_PARAM_NAMES.end()) { if (!MG_Constants::Common::Contains(pname, MG_Constants::Buffer::VALID_PARAM_NAMES)) {
return GL_INVALID_ENUM; return GL_INVALID_ENUM;
} }
@@ -291,12 +297,12 @@ GLenum BufferState::QueryPropertyIntVector(GLenum target, GLenum pname, GLint* p
return GL_INVALID_OPERATION; return GL_INVALID_OPERATION;
} }
GLuint bufferId = bindingIt->second; GLuint bufferId = bindingIt->second;
auto bufferIt = buffers_.find(bufferId);
if (bufferIt == buffers_.end()) { if (!ValidateAllocatedHandle(bufferId)) {
return GL_INVALID_OPERATION; return GL_INVALID_OPERATION;
} }
const BufferObject& buffer = bufferIt->second; const BufferObject& buffer = *bufferObjects_[bufferId];
switch (pname) { switch (pname) {
case GL_BUFFER_ACCESS: case GL_BUFFER_ACCESS:
@@ -325,4 +331,15 @@ GLuint BufferState::GetCurrentBinding(GLenum target) const {
return it->second; return it->second;
} }
return 0; return 0;
} }
BufferState::BufferObject* BufferState::GetBufferObject(GLuint buffer) {
if (bufferObjects_.size() <= buffer) {
return nullptr;
}
// if (bufferObjects_[buffer] == nullptr) {
// raise(SIGTRAP);
//// bufferObjects_[buffer] = std::make_unique<BufferObject>();
// }
return bufferObjects_[buffer].get();
}
+12 -13
View File
@@ -4,14 +4,8 @@
#ifndef MOBILEGL_BUFFERSTATE_H #ifndef MOBILEGL_BUFFERSTATE_H
#define MOBILEGL_BUFFERSTATE_H #define MOBILEGL_BUFFERSTATE_H
#define MOBILEGL_GLSTATE_H
#include "../../../Includes.h"
class BufferState { class BufferState {
template <typename K, typename V>
using unordered_map = ankerl::unordered_dense::map<K, V>;
public: public:
struct BufferObject { struct BufferObject {
GLenum usage = GL_STATIC_DRAW; GLenum usage = GL_STATIC_DRAW;
@@ -20,6 +14,7 @@ public:
bool dirty = false; // TODO: encapsulate this with an public API to RHI bool dirty = false; // TODO: encapsulate this with an public API to RHI
bool isMapped = false; bool isMapped = false;
bool generated = false; bool generated = false;
bool isDynamic = false;
GLenum accessMode = GL_READ_WRITE; GLenum accessMode = GL_READ_WRITE;
GLintptr mapOffset = 0; GLintptr mapOffset = 0;
GLsizeiptr mapLength = 0; GLsizeiptr mapLength = 0;
@@ -27,7 +22,7 @@ public:
}; };
// Return: the validity of the operation, according to OpenGL 3 standard // Return: the validity of the operation, according to OpenGL 3 standard
GLenum GenName(GLuint* buffer); // GLenum GenName(GLuint* buffer);
GLenum GenNameN(GLsizei n, GLuint* buffers); GLenum GenNameN(GLsizei n, GLuint* buffers);
GLenum Create(GLuint buffer); GLenum Create(GLuint buffer);
GLenum Bind(GLenum target, GLuint buffer); GLenum Bind(GLenum target, GLuint buffer);
@@ -41,16 +36,20 @@ public:
GLenum QueryPropertyIntVector(GLenum target, GLenum pname, GLint* params) const; GLenum QueryPropertyIntVector(GLenum target, GLenum pname, GLint* params) const;
GLenum DeleteN(GLsizei n, const GLuint* buffers); GLenum DeleteN(GLsizei n, const GLuint* buffers);
bool ValidateAllocatedHandle(GLuint buffer); bool ValidateAllocatedHandle(GLuint buffer) const;
bool ValidateGeneratedName(GLuint buffer); bool ValidateGeneratedName(GLuint buffer) const;
void Delete(GLuint buffer); void Delete(GLuint buffer);
GLuint GetCurrentBinding(GLenum target) const; GLuint GetCurrentBinding(GLenum target) const;
unordered_map<GLenum, GLuint> currentBindings_; BufferObject* GetBufferObject(GLuint buffer);
unordered_map<GLuint, BufferObject> buffers_;
MG_Global::unordered_map<GLenum, GLuint> currentBindings_;
// MG_Global::unordered_map<GLuint, BufferObject> buffers_;
private: private:
std::vector<GLuint> freeId_; // std::vector<GLuint> freeId_;
GLuint lastId_ = 1; // GLuint lastId_ = 1;
IndexGenerator<GLuint> indexGenerator_;
std::vector<std::unique_ptr<BufferObject>> bufferObjects_;
static bool IsValidTarget_(GLenum target); static bool IsValidTarget_(GLenum target);
}; };
+12 -11
View File
@@ -2,7 +2,7 @@
// Created by BZLZHH on 2025/4/30. // Created by BZLZHH on 2025/4/30.
// //
#include "CommonState.h" #include "../../../Includes.h"
CommonState::CommonState() { CommonState::CommonState() {
pixelStoreParams[GL_PACK_ALIGNMENT] = 4; pixelStoreParams[GL_PACK_ALIGNMENT] = 4;
@@ -10,7 +10,7 @@ CommonState::CommonState() {
} }
GLenum CommonState::SetPixelStoreInt(GLenum pname, GLint param) { GLenum CommonState::SetPixelStoreInt(GLenum pname, GLint param) {
if (MG_Constants::PixelStore::VALID_PARAM_NAMES.find(pname) == MG_Constants::PixelStore::VALID_PARAM_NAMES.end()) { if (!MG_Constants::Common::Contains(pname, MG_Constants::PixelStore::VALID_PARAM_NAMES)) {
return GL_INVALID_ENUM; return GL_INVALID_ENUM;
} }
@@ -61,7 +61,7 @@ GLint CommonState::QueryPixelStoreInt(GLenum pname) {
} }
GLenum CommonState::Enable(GLenum cap) { GLenum CommonState::Enable(GLenum cap) {
if (MG_Constants::CommonState::VALID_CAPS.find(cap) == MG_Constants::CommonState::VALID_CAPS.end()) { if (!MG_Constants::Common::Contains(cap, MG_Constants::CommonState::VALID_CAPS)) {
return GL_INVALID_ENUM; return GL_INVALID_ENUM;
} }
capabilities[cap] = true; capabilities[cap] = true;
@@ -69,7 +69,7 @@ GLenum CommonState::Enable(GLenum cap) {
} }
GLenum CommonState::Disable(GLenum cap) { GLenum CommonState::Disable(GLenum cap) {
if (MG_Constants::CommonState::VALID_CAPS.find(cap) == MG_Constants::CommonState::VALID_CAPS.end()) { if (!MG_Constants::Common::Contains(cap, MG_Constants::CommonState::VALID_CAPS)) {
return GL_INVALID_ENUM; return GL_INVALID_ENUM;
} }
capabilities[cap] = false; capabilities[cap] = false;
@@ -77,8 +77,8 @@ GLenum CommonState::Disable(GLenum cap) {
} }
GLenum CommonState::BlendFunc(GLenum sfactor, GLenum dfactor) { GLenum CommonState::BlendFunc(GLenum sfactor, GLenum dfactor) {
if (MG_Constants::Blend::VALID_FACTORS.find(sfactor) == MG_Constants::Blend::VALID_FACTORS.end() || if (!MG_Constants::Common::Contains(sfactor, MG_Constants::Blend::VALID_FACTORS) ||
MG_Constants::Blend::VALID_FACTORS.find(dfactor) == MG_Constants::Blend::VALID_FACTORS.end()) { !MG_Constants::Common::Contains(dfactor, MG_Constants::Blend::VALID_FACTORS)) {
return GL_INVALID_ENUM; return GL_INVALID_ENUM;
} }
@@ -89,10 +89,10 @@ GLenum CommonState::BlendFunc(GLenum sfactor, GLenum dfactor) {
GLenum CommonState::BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum CommonState::BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB,
GLenum srcAlpha, GLenum dstAlpha) { GLenum srcAlpha, GLenum dstAlpha) {
if (MG_Constants::Blend::VALID_FACTORS.find(srcRGB) == MG_Constants::Blend::VALID_FACTORS.end() || if (!MG_Constants::Common::Contains(srcRGB, MG_Constants::Blend::VALID_FACTORS) ||
MG_Constants::Blend::VALID_FACTORS.find(dstRGB) == MG_Constants::Blend::VALID_FACTORS.end() || !MG_Constants::Common::Contains(dstRGB, MG_Constants::Blend::VALID_FACTORS) ||
MG_Constants::Blend::VALID_FACTORS.find(srcAlpha) == MG_Constants::Blend::VALID_FACTORS.end() || !MG_Constants::Common::Contains(srcAlpha, MG_Constants::Blend::VALID_FACTORS) ||
MG_Constants::Blend::VALID_FACTORS.find(dstAlpha) == MG_Constants::Blend::VALID_FACTORS.end()) { !MG_Constants::Common::Contains(dstAlpha, MG_Constants::Blend::VALID_FACTORS)) {
return GL_INVALID_ENUM; return GL_INVALID_ENUM;
} }
blendSrcRGB = srcRGB; blendSrcRGB = srcRGB;
@@ -133,10 +133,11 @@ GLenum CommonState::ColorMask(GLboolean red, GLboolean green, GLboolean blue, GL
} }
GLenum CommonState::DepthFunc(GLenum func) { GLenum CommonState::DepthFunc(GLenum func) {
if (MG_Constants::Depth::VALID_FUNCS.find(func) == MG_Constants::Depth::VALID_FUNCS.end()) { if (!MG_Constants::Common::Contains(func, MG_Constants::Depth::VALID_FUNCS)) {
return GL_INVALID_ENUM; return GL_INVALID_ENUM;
} }
depthFunc = func; depthFunc = func;
MG_Util::Debug::LogD("%s(%s)", __func__, MG_Util::Debug::GLEnumToString(func));
return GL_NO_ERROR; return GL_NO_ERROR;
} }
+2 -7
View File
@@ -4,13 +4,8 @@
#ifndef MOBILEGL_COMMONSTATE_H #ifndef MOBILEGL_COMMONSTATE_H
#define MOBILEGL_COMMONSTATE_H #define MOBILEGL_COMMONSTATE_H
#define MOBILEGL_GLSTATE_H
#include "../../../Includes.h"
class CommonState { class CommonState {
template <typename K, typename V>
using unordered_map = ankerl::unordered_dense::map<K, V>;
public: public:
// Viewport // Viewport
GLint viewport[4] = {0, 0, 0, 0}; GLint viewport[4] = {0, 0, 0, 0};
@@ -19,7 +14,7 @@ public:
GLboolean colorMask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE}; GLboolean colorMask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
// Pixel storage parameters // Pixel storage parameters
unordered_map<GLenum, GLint> pixelStoreParams; MG_Global::unordered_map<GLenum, GLint> pixelStoreParams;
// Blend state // Blend state
GLenum blendSrcRGB = GL_ONE; GLenum blendSrcRGB = GL_ONE;
@@ -37,7 +32,7 @@ public:
GLboolean depthMask = GL_TRUE; GLboolean depthMask = GL_TRUE;
// Capability enables // Capability enables
unordered_map<GLenum, bool> capabilities; MG_Global::unordered_map<GLenum, bool> capabilities;
CommonState(); CommonState();
+5 -5
View File
@@ -2,7 +2,7 @@
// Created by BZLZHH on 2025/4/4. // Created by BZLZHH on 2025/4/4.
// //
#include "GLState.h" #include "../../../Includes.h"
std::queue<GLenum> MG_State_T::glErrorQueue; std::queue<GLenum> MG_State_T::glErrorQueue;
TextureState* MG_State_T::textureState = nullptr; TextureState* MG_State_T::textureState = nullptr;
@@ -298,12 +298,12 @@ namespace MG_State {
return MG_State_T::programState->ActivateRenderProgram(program); return MG_State_T::programState->ActivateRenderProgram(program);
} }
GLenum DefineProgramAttributeBinding(GLuint program, GLuint index, const GLchar* name) { GLenum DefineProgramAttributeLocation(GLuint program, GLuint index, const GLchar* name) {
return MG_State_T::programState->DefineProgramAttributeBinding(program, index, name); return MG_State_T::programState->DefineProgramAttributeLocation(program, index, name);
} }
GLint QueryProgramAttributeBinding(GLuint program, const GLchar* name) { GLint QueryProgramAttributeLocation(GLuint program, const GLchar* name) {
return MG_State_T::programState->QueryProgramAttributeBinding(program, name); return MG_State_T::programState->QueryProgramAttributeLocation(program, name);
} }
GLint QueryProgramUniformLocation(GLuint program, const GLchar* name) { GLint QueryProgramUniformLocation(GLuint program, const GLchar* name) {
+2 -4
View File
@@ -5,8 +5,6 @@
#ifndef MOBILEGL_GLSTATE_H #ifndef MOBILEGL_GLSTATE_H
#define MOBILEGL_GLSTATE_H #define MOBILEGL_GLSTATE_H
#include "../../../Includes.h"
struct MG_State_T { struct MG_State_T {
static std::queue<GLenum> glErrorQueue; static std::queue<GLenum> glErrorQueue;
static TextureState* textureState; static TextureState* textureState;
@@ -95,8 +93,8 @@ namespace MG_State {
GLenum BuildShaderStage(GLuint shader); GLenum BuildShaderStage(GLuint shader);
GLenum FinalizeProgramPipeline(GLuint program); GLenum FinalizeProgramPipeline(GLuint program);
GLenum ActivateRenderProgram(GLuint program); GLenum ActivateRenderProgram(GLuint program);
GLenum DefineProgramAttributeBinding(GLuint program, GLuint index, const GLchar* name); GLenum DefineProgramAttributeLocation(GLuint program, GLuint index, const GLchar* name);
GLint QueryProgramAttributeBinding(GLuint program, const GLchar* name); GLint QueryProgramAttributeLocation(GLuint program, const GLchar* name);
GLint QueryProgramUniformLocation(GLuint program, const GLchar* name); GLint QueryProgramUniformLocation(GLuint program, const GLchar* name);
GLenum QueryProgramStateIntVector(GLuint program, GLenum pname, GLint* params); GLenum QueryProgramStateIntVector(GLuint program, GLenum pname, GLint* params);
GLenum QueryShaderStateIntVector(GLuint shader, GLenum pname, GLint* params); GLenum QueryShaderStateIntVector(GLuint shader, GLenum pname, GLint* params);
@@ -5,10 +5,6 @@
// TODO: Add more gl error check for framebuffer state manager. // TODO: Add more gl error check for framebuffer state manager.
// TODO: Check if the state machine really meets up to OpenGL 3 standard. // TODO: Check if the state machine really meets up to OpenGL 3 standard.
#include "FramebufferState.h"
// Re-Include Includes.h, cuz of the absence of GLState.h
#undef MOBILEGL_GLSTATE_H
#include "../../../Includes.h" #include "../../../Includes.h"
GLenum FramebufferState::Create(GLuint* framebuffer) { GLenum FramebufferState::Create(GLuint* framebuffer) {
@@ -42,7 +38,7 @@ GLenum FramebufferState::Delete(GLuint framebuffer) {
} }
GLenum FramebufferState::Bind(GLenum target, GLuint framebuffer) { GLenum FramebufferState::Bind(GLenum target, GLuint framebuffer) {
if (MG_Constants::Framebuffer::VALID_TARGETS.find(target) == MG_Constants::Framebuffer::VALID_TARGETS.end()) if (!MG_Constants::Common::Contains(target, MG_Constants::Framebuffer::VALID_TARGETS))
return GL_INVALID_ENUM; return GL_INVALID_ENUM;
if (framebuffer != 0 && !ValidateHandle(framebuffer)) if (framebuffer != 0 && !ValidateHandle(framebuffer))
return GL_INVALID_OPERATION; return GL_INVALID_OPERATION;
@@ -57,10 +53,28 @@ GLenum FramebufferState::Bind(GLenum target, GLuint framebuffer) {
GLenum FramebufferState::AttachTexture2D(GLenum target, GLenum attachment, GLenum FramebufferState::AttachTexture2D(GLenum target, GLenum attachment,
GLenum textarget, GLuint texture, GLint level) { GLenum textarget, GLuint texture, GLint level) {
if (MG_Constants::Framebuffer::VALID_ATTACHMENTS.find(attachment) == MG_Constants::Framebuffer::VALID_ATTACHMENTS.end() || if (!MG_Constants::Common::Contains(attachment, MG_Constants::Framebuffer::VALID_ATTACHMENTS) ||
MG_Constants::Texture::VALID_TARGETS.find(textarget) == MG_Constants::Texture::VALID_TARGETS.end()) !MG_Constants::Common::Contains(textarget, MG_Constants::Texture::VALID_TARGETS))
return GL_INVALID_ENUM; return GL_INVALID_ENUM;
if (target == GL_FRAMEBUFFER) target = GL_DRAW_FRAMEBUFFER; if (target == GL_FRAMEBUFFER) {
target = GL_DRAW_FRAMEBUFFER;
// if (currentBindings_[GL_READ_FRAMEBUFFER] == currentBindings_[GL_DRAW_FRAMEBUFFER]) {
// target = GL_DRAW_FRAMEBUFFER;
// } else {
// if (currentBindings_[GL_READ_FRAMEBUFFER] != 0) {
// GLenum err = AttachTexture2D(GL_READ_FRAMEBUFFER, attachment, textarget, texture, level);
// if (err != GL_NO_ERROR)
// return err;
// }
// if (currentBindings_[GL_DRAW_FRAMEBUFFER] != 0) {
// GLenum err = AttachTexture2D(GL_DRAW_FRAMEBUFFER, attachment, textarget, texture, level);
// if (err != GL_NO_ERROR)
// return err;
// }
// return GL_NO_ERROR;
// }
}
FramebufferObject* fbo = GetCurrentFBO(target); FramebufferObject* fbo = GetCurrentFBO(target);
if (!fbo) return GL_INVALID_OPERATION; if (!fbo) return GL_INVALID_OPERATION;
if (texture != 0 && !MG_State_T::textureState->IsTexture(texture)) if (texture != 0 && !MG_State_T::textureState->IsTexture(texture))
@@ -4,9 +4,6 @@
#ifndef MOBILEGL_FRAMEBUFFERSTATE_H #ifndef MOBILEGL_FRAMEBUFFERSTATE_H
#define MOBILEGL_FRAMEBUFFERSTATE_H #define MOBILEGL_FRAMEBUFFERSTATE_H
#define MOBILEGL_GLSTATE_H
#include "../../../Includes.h"
struct FramebufferAttachment { struct FramebufferAttachment {
GLenum type = GL_NONE; GLenum type = GL_NONE;
@@ -17,7 +14,7 @@ struct FramebufferAttachment {
struct FramebufferObject { struct FramebufferObject {
bool generated = false; bool generated = false;
ankerl::unordered_map<GLenum, FramebufferAttachment> attachments; MG_Global::unordered_map<GLenum, FramebufferAttachment> attachments;
GLenum status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; GLenum status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
GLsizei width = 0; GLsizei width = 0;
GLsizei height = 0; GLsizei height = 0;
@@ -35,10 +32,10 @@ public:
GLenum ValidateCompleteness(GLenum target); GLenum ValidateCompleteness(GLenum target);
FramebufferObject* GetCurrentFBO(GLenum target); FramebufferObject* GetCurrentFBO(GLenum target);
ankerl::unordered_map<GLenum, GLuint> currentBindings_; // READ/DRAW MG_Global::unordered_map<GLenum, GLuint> currentBindings_; // READ/DRAW
private: private:
ankerl::unordered_map<GLuint, FramebufferObject> framebuffers_; MG_Global::unordered_map<GLuint, FramebufferObject> framebuffers_;
std::set<GLuint> freeIds_; std::set<GLuint> freeIds_;
GLuint lastId_ = 0; GLuint lastId_ = 0;
bool ValidateHandle(GLuint framebuffer); bool ValidateHandle(GLuint framebuffer);
+51 -28
View File
@@ -4,11 +4,6 @@
// TODO: Add more gl error check for buffer state manager. // TODO: Add more gl error check for buffer state manager.
// TODO: Check if the state machine really meets up to OpenGL 3 standard. // TODO: Check if the state machine really meets up to OpenGL 3 standard.
#include "ProgramState.h"
// Re-Include Includes.h, cuz of the absence of Program/DebugTool.h and Program/GLSLTool.cpp.
#undef MOBILEGL_GLSLTOOL_H
#undef MOBILEGL_PROGRAM_DEBUGTOOL_H
#include "../../../Includes.h" #include "../../../Includes.h"
ProgramState::ProgramState() { ProgramState::ProgramState() {
@@ -110,7 +105,21 @@ GLenum ProgramState::FinalizeProgramPipeline(GLuint program) {
std::vector<std::vector<unsigned>> allSpirv = std::vector<std::vector<unsigned>> allSpirv =
MG_Util::Program::CompileMultipleShadersToSPIRV(*this, prog, prog.infoLog); MG_Util::Program::CompileMultipleShadersToSPIRV(*this, prog, prog.infoLog);
if (!prog.infoLog.empty() || allSpirv.empty()) {
prog.linked = UncertainBool::False;
prog.linkStatus = GL_FALSE;
prog.infoLog = "Program linking failed during SPIR-V compilation: " + prog.infoLog;
MG_Util::Debug::LogE("MG_State: Program: FinalizeProgramPipeline error: %s", prog.infoLog.c_str());
return GL_INVALID_OPERATION;
}
MG_Util::Program::ReflectSPIRVUniforms(allSpirv, prog, prog.infoLog); MG_Util::Program::ReflectSPIRVUniforms(allSpirv, prog, prog.infoLog);
for (size_t i = 0; i < prog.attachedShaders.size(); ++i) {
GLuint shaderId = prog.attachedShaders[i];
shaders_[shaderId].source = MG_Util::Program::CompileSPIRVToGLSL(allSpirv[i], 450, false, false);
}
if (!prog.infoLog.empty()) { if (!prog.infoLog.empty()) {
prog.linked = UncertainBool::False; prog.linked = UncertainBool::False;
prog.linkStatus = GL_FALSE; prog.linkStatus = GL_FALSE;
@@ -118,10 +127,8 @@ GLenum ProgramState::FinalizeProgramPipeline(GLuint program) {
MG_Util::Debug::LogE("MG_State: Program: FinalizeProgramPipeline error: %s", prog.infoLog.c_str()); MG_Util::Debug::LogE("MG_State: Program: FinalizeProgramPipeline error: %s", prog.infoLog.c_str());
return GL_INVALID_OPERATION; return GL_INVALID_OPERATION;
} }
for (auto& [name, index] : prog.attribBindings) { // TODO: Support explicitly assign attrib locations in the shaders.
prog.attribLocations[name] = index;
}
prog.linked = {UncertainBool::Unknown, UncertainBool::True}; prog.linked = {UncertainBool::Unknown, UncertainBool::True};
prog.linkStatus = GL_TRUE; prog.linkStatus = GL_TRUE;
@@ -147,28 +154,28 @@ GLenum ProgramState::ActivateRenderProgram(GLuint program) {
return GL_NO_ERROR; return GL_NO_ERROR;
} }
GLenum ProgramState::DefineProgramAttributeBinding(GLuint program, GLuint index, const GLchar* name) { GLenum ProgramState::DefineProgramAttributeLocation(GLuint program, GLuint index, const GLchar* name) {
MG_Util::Debug::LogD("MG_State: Program: DefineProgramAttributeBinding called, program=%u, index=%u, name=%s", MG_Util::Debug::LogD("MG_State: Program: DefineProgramAttributeLocation called, program=%u, index=%u, name=%s",
program, index, name); program, index, name);
if (!ValidateProgram_(program)) { if (!ValidateProgram_(program)) {
MG_Util::Debug::LogE("MG_State: Program: DefineProgramAttributeBinding error: invalid program id %u", program); MG_Util::Debug::LogE("MG_State: Program: DefineProgramAttributeLocation error: invalid program id %u", program);
return GL_INVALID_VALUE; return GL_INVALID_VALUE;
} }
if (index >= GL_MAX_VERTEX_ATTRIBS) { if (index >= GL_MAX_VERTEX_ATTRIBS) {
MG_Util::Debug::LogE("MG_State: Program: DefineProgramAttributeBinding error: index %u out of range", index); MG_Util::Debug::LogE("MG_State: Program: DefineProgramAttributeLocation error: index %u out of range", index);
return GL_INVALID_VALUE; return GL_INVALID_VALUE;
} }
programs_[program].attribBindings[name] = index; programs_[program].attribLocations[name] = index;
MG_Util::Debug::LogD("MG_State: Program: DefineProgramAttributeBinding success: %s -> %u", name, index); MG_Util::Debug::LogD("MG_State: Program: DefineProgramAttributeLocation success: %s -> %u", name, index);
return GL_NO_ERROR; return GL_NO_ERROR;
} }
GLint ProgramState::QueryProgramAttributeBinding(GLuint program, const GLchar* name) { GLint ProgramState::QueryProgramAttributeLocation(GLuint program, const GLchar* name) {
MG_Util::Debug::LogD("MG_State: Program: QueryProgramAttributeBinding called, program=%u, name=%s", MG_Util::Debug::LogD("MG_State: Program: QueryProgramAttributeLocation called, program=%u, name=%s",
program, name); program, name);
if (!ValidateProgram_(program)) { if (!ValidateProgram_(program)) {
MG_Util::Debug::LogE("MG_State: Program: QueryProgramAttributeBinding error: invalid program id %u", program); MG_Util::Debug::LogE("MG_State: Program: QueryProgramAttributeLocation error: invalid program id %u", program);
return -1; return -1;
} }
@@ -176,11 +183,27 @@ GLint ProgramState::QueryProgramAttributeBinding(GLuint program, const GLchar* n
auto it = prog.attribLocations.find(name); auto it = prog.attribLocations.find(name);
if (it != prog.attribLocations.end()) { if (it != prog.attribLocations.end()) {
GLint loc = it->second; GLint loc = it->second;
MG_Util::Debug::LogD("MG_State: Program: QueryProgramAttributeBinding success: %s -> %d", name, loc); MG_Util::Debug::LogD("MG_State: Program: QueryProgramAttributeLocation success: %s -> %d", name, loc);
return loc; return loc;
} else {
MG_Util::Debug::LogW("MG_State: Program: QueryProgramAttributeLocation warning: name '%s' not found, generating new one...", name);
// Find the next available location
GLint loc = (GLint)prog.attribLocations.size();
bool locInUse;
do {
locInUse = false;
for (const auto& pair : prog.attribLocations) {
if (pair.second == loc) {
locInUse = true;
loc++;
break;
}
}
} while (locInUse);
prog.attribLocations[name] = loc;
MG_Util::Debug::LogD("MG_State: Program: QueryProgramAttributeLocation success: %s -> %d", name, loc);
return prog.attribLocations[name];
} }
MG_Util::Debug::LogW("MG_State: Program: QueryProgramAttributeBinding warning: name '%s' not found", name);
return -1;
} }
GLenum ProgramState::QueryProgramStateIntVector(GLuint program, GLenum pname, GLint* params) { GLenum ProgramState::QueryProgramStateIntVector(GLuint program, GLenum pname, GLint* params) {
@@ -408,26 +431,26 @@ GLuint ProgramState::GetCurrentProgram() const {
return currentProgram_; return currentProgram_;
} }
ShaderObject ProgramState::GetShaderObject(GLuint shader) const { const ShaderObject* ProgramState::GetShaderObject(GLuint shader) const {
MG_Util::Debug::LogD("MG_State: Program: GetShaderObject called, shader=%u", shader); MG_Util::Debug::LogD("MG_State: Program: GetShaderObject called, shader=%u", shader);
auto it = shaders_.find(shader); auto it = shaders_.find(shader);
if (it == shaders_.end()) { if (it == shaders_.end()) {
MG_Util::Debug::LogW("MG_State: Program: GetShaderObject warning: invalid shader id %u", shader); MG_Util::Debug::LogW("MG_State: Program: GetShaderObject warning: invalid shader id %u", shader);
return ShaderObject(); return nullptr;
} }
MG_Util::Debug::LogD("MG_State: Program: GetShaderObject success, returning object"); MG_Util::Debug::LogD("MG_State: Program: GetShaderObject success, returning object");
return it->second; return &(it->second);
} }
ProgramObject ProgramState::GetProgramObject(GLuint program) const { const ProgramObject* ProgramState::GetProgramObject(GLuint program) const {
MG_Util::Debug::LogD("MG_State: Program: GetProgramObject called, program=%u", program); MG_Util::Debug::LogD("MG_State: Program: GetProgramObject called, program=%u", program);
auto it = programs_.find(program); auto it = programs_.find(program);
if (it == programs_.end()) { if (it == programs_.end()) {
MG_Util::Debug::LogW("MG_State: Program: GetProgramObject warning: invalid program id %u", program); MG_Util::Debug::LogW("MG_State: Program: GetProgramObject warning: invalid program id %u", program);
return ProgramObject(); return nullptr;
} }
MG_Util::Debug::LogD("MG_State: Program: GetProgramObject success, returning object"); MG_Util::Debug::LogD("MG_State: Program: GetProgramObject success, returning object");
return it->second; return &(it->second);
} }
bool ProgramState::ValidateProgram_(GLuint program) { bool ProgramState::ValidateProgram_(GLuint program) {
@@ -451,7 +474,7 @@ void ProgramState::CleanupShaders_() {
} }
if (!inUse) { if (!inUse) {
MG_Util::Debug::LogD("MG_State: Program: CleanupShaders_ deleting shader %u", it->first); MG_Util::Debug::LogD("MG_State: Program: CleanupShaders_ deleting shader %u", it->first);
freeShaderIds_.insert(it->first); // freeShaderIds_.insert(it->first);
it = shaders_.erase(it); it = shaders_.erase(it);
continue; continue;
} }
+9 -15
View File
@@ -4,11 +4,6 @@
#ifndef MOBILEGL_PROGRAMSTATE_H #ifndef MOBILEGL_PROGRAMSTATE_H
#define MOBILEGL_PROGRAMSTATE_H #define MOBILEGL_PROGRAMSTATE_H
#define MOBILEGL_GLSTATE_H
#define MOBILEGL_PROGRAM_DEBUGTOOL_H
#define MOBILEGL_GLSLTOOL_H
#include "../../../Includes.h"
struct ShaderObject { struct ShaderObject {
GLenum type; GLenum type;
@@ -41,17 +36,16 @@ struct ProgramObject {
bool dirty; bool dirty;
GLint linkStatus; GLint linkStatus;
std::string infoLog; std::string infoLog;
ankerl::unordered_map<std::string, GLint> attribBindings; MG_Global::unordered_map<std::string, GLint> attribLocations;
ankerl::unordered_map<std::string, GLint> attribLocations; MG_Global::unordered_map<std::string, GLint> uniformLocations;
ankerl::unordered_map<std::string, GLint> uniformLocations; MG_Global::unordered_map<std::string, UniformValue> uniformValues;
ankerl::unordered_map<std::string, UniformValue> uniformValues;
bool markedForDeletion; bool markedForDeletion;
}; };
class ProgramState { class ProgramState {
public: public:
ankerl::unordered_map<GLuint, ShaderObject> shaders_; MG_Global::unordered_map<GLuint, ShaderObject> shaders_;
ankerl::unordered_map<GLuint, ProgramObject> programs_; MG_Global::unordered_map<GLuint, ProgramObject> programs_;
std::set<GLuint> freeShaderIds_; std::set<GLuint> freeShaderIds_;
std::set<GLuint> freeProgramIds_; std::set<GLuint> freeProgramIds_;
GLuint lastShaderId_ = 0; GLuint lastShaderId_ = 0;
@@ -71,8 +65,8 @@ public:
GLenum BuildShaderStage(GLuint shader); GLenum BuildShaderStage(GLuint shader);
GLenum FinalizeProgramPipeline(GLuint program); GLenum FinalizeProgramPipeline(GLuint program);
GLenum ActivateRenderProgram(GLuint program); GLenum ActivateRenderProgram(GLuint program);
GLenum DefineProgramAttributeBinding(GLuint program, GLuint index, const GLchar* name); GLenum DefineProgramAttributeLocation(GLuint program, GLuint index, const GLchar* name);
GLint QueryProgramAttributeBinding(GLuint program, const GLchar* name); GLint QueryProgramAttributeLocation(GLuint program, const GLchar* name);
GLint QueryProgramUniformLocation(GLuint program, const GLchar* name); GLint QueryProgramUniformLocation(GLuint program, const GLchar* name);
GLenum QueryProgramStateIntVector(GLuint program, GLenum pname, GLint* params); GLenum QueryProgramStateIntVector(GLuint program, GLenum pname, GLint* params);
GLenum QueryShaderStateIntVector(GLuint shader, GLenum pname, GLint* params); GLenum QueryShaderStateIntVector(GLuint shader, GLenum pname, GLint* params);
@@ -110,8 +104,8 @@ public:
DECLARE_MATRIX_FUNCTIONS(4x3, GL_FLOAT_MAT4x3) DECLARE_MATRIX_FUNCTIONS(4x3, GL_FLOAT_MAT4x3)
#undef DECLARE_MATRIX_FUNCTIONS #undef DECLARE_MATRIX_FUNCTIONS
ProgramObject GetProgramObject(GLuint program) const; const ProgramObject* GetProgramObject(GLuint program) const;
ShaderObject GetShaderObject(GLuint program) const; const ShaderObject* GetShaderObject(GLuint program) const;
GLuint GetCurrentProgram() const; GLuint GetCurrentProgram() const;
bool SetProgramStatus(GLuint program, GLboolean status); bool SetProgramStatus(GLuint program, GLboolean status);
bool SetShaderStatus(GLuint shader, GLboolean status); bool SetShaderStatus(GLuint shader, GLboolean status);
-9
View File
@@ -2,11 +2,6 @@
// Created by BZLZHH on 2025/5/3. // Created by BZLZHH on 2025/5/3.
// //
#include "ShaderObject.h"
// Re-Include Includes.h, cuz of the absence of Program/DebugTool.h and Program/GLSLTool.cpp.
#undef MOBILEGL_GLSLTOOL_H
#undef MOBILEGL_PROGRAM_DEBUGTOOL_H
#include "../../../Includes.h" #include "../../../Includes.h"
GLenum ProgramState::CreateShader(GLenum type, GLuint* shader) { GLenum ProgramState::CreateShader(GLenum type, GLuint* shader) {
@@ -42,10 +37,6 @@ GLenum ProgramState::DeleteShader(GLuint shader) {
MG_Util::Debug::LogE("MG_State: Program: DeleteShader error: invalid shader id %u", shader); MG_Util::Debug::LogE("MG_State: Program: DeleteShader error: invalid shader id %u", shader);
return GL_INVALID_VALUE; return GL_INVALID_VALUE;
} }
if (shaders_[shader].markedForDeletion) {
MG_Util::Debug::LogW("MG_State: Program: DeleteShader warning: shader %u already marked for deletion", shader);
return GL_NO_ERROR;
}
bool inUse = false; bool inUse = false;
for (auto& [progId, program] : programs_) { for (auto& [progId, program] : programs_) {
-4
View File
@@ -5,8 +5,4 @@
#ifndef MOBILEGL_SHADEROBJECT_H #ifndef MOBILEGL_SHADEROBJECT_H
#define MOBILEGL_SHADEROBJECT_H #define MOBILEGL_SHADEROBJECT_H
#define MOBILEGL_GLSTATE_H
#include "../../../Includes.h"
#endif //MOBILEGL_SHADEROBJECT_H #endif //MOBILEGL_SHADEROBJECT_H
+15 -20
View File
@@ -2,10 +2,6 @@
// Created by BZLZHH on 2025/4/4. // Created by BZLZHH on 2025/4/4.
// //
#include "TextureState.h"
// Re-Include Includes.h, cuz of the absence of GLState.h
#undef MOBILEGL_GLSTATE_H
#include "../../../Includes.h" #include "../../../Includes.h"
// TextureObject // TextureObject
@@ -121,7 +117,7 @@ GLenum TextureState::CreateN(GLsizei n, GLuint* textures) {
GLenum TextureState::Bind(GLenum target, GLuint texture) { GLenum TextureState::Bind(GLenum target, GLuint texture) {
MG_Util::Debug::LogD("MG_State: Texture: Bind called with target=0x%x, texture=%u", target, texture); MG_Util::Debug::LogD("MG_State: Texture: Bind called with target=0x%x, texture=%u", target, texture);
if (MG_Constants::Texture::VALID_TARGETS.find(target) == MG_Constants::Texture::VALID_TARGETS.end()) { if (!MG_Constants::Common::Contains(target, MG_Constants::Texture::VALID_TARGETS)) {
MG_Util::Debug::LogE("MG_State: Texture: Bind invalid target=0x%x", target); MG_Util::Debug::LogE("MG_State: Texture: Bind invalid target=0x%x", target);
return GL_INVALID_ENUM; return GL_INVALID_ENUM;
} }
@@ -146,7 +142,6 @@ GLenum TextureState::Bind(GLenum target, GLuint texture) {
} }
} }
TextureUnitState& unit = textureUnits_[activeTextureUnit_]; TextureUnitState& unit = textureUnits_[activeTextureUnit_];
TextureObject* texObj = nullptr; TextureObject* texObj = nullptr;
auto it = this->textures.find(texture); auto it = this->textures.find(texture);
@@ -498,12 +493,12 @@ GLenum TextureState::UpdateRegion2D(GLenum target, GLint level, GLint xoffset,
GLenum TextureState::SetTexturePropertyFloat(GLenum target, GLenum pname, GLfloat param) { GLenum TextureState::SetTexturePropertyFloat(GLenum target, GLenum pname, GLfloat param) {
MG_Util::Debug::LogD("MG_State: Texture: SetTexturePropertyFloat called target=0x%x, pname=0x%x, param=%f", target, pname, param); MG_Util::Debug::LogD("MG_State: Texture: SetTexturePropertyFloat called target=0x%x, pname=0x%x, param=%f", target, pname, param);
if (MG_Constants::Texture::VALID_TARGETS.find(target) == MG_Constants::Texture::VALID_TARGETS.end()) { if (!MG_Constants::Common::Contains(target, MG_Constants::Texture::VALID_TARGETS)) {
MG_Util::Debug::LogE("MG_State: Texture: SetTexturePropertyFloat invalid target=0x%x", target); MG_Util::Debug::LogE("MG_State: Texture: SetTexturePropertyFloat invalid target=0x%x", target);
return GL_INVALID_ENUM; return GL_INVALID_ENUM;
} }
if (MG_Constants::Texture::VALID_TEXTURE_PARAM_NAMES.find(pname) == MG_Constants::Texture::VALID_TEXTURE_PARAM_NAMES.end()) { if (!MG_Constants::Common::Contains(pname, MG_Constants::Texture::VALID_TEXTURE_PARAM_NAMES)) {
MG_Util::Debug::LogE("MG_State: Texture: SetTexturePropertyFloat invalid pname=0x%x", pname); MG_Util::Debug::LogE("MG_State: Texture: SetTexturePropertyFloat invalid pname=0x%x", pname);
return GL_INVALID_ENUM; return GL_INVALID_ENUM;
} }
@@ -550,12 +545,12 @@ GLenum TextureState::SetTexturePropertyFloat(GLenum target, GLenum pname, GLfloa
GLenum TextureState::SetTexturePropertyInt(GLenum target, GLenum pname, GLint param) { GLenum TextureState::SetTexturePropertyInt(GLenum target, GLenum pname, GLint param) {
MG_Util::Debug::LogD("MG_State: Texture: SetTexturePropertyInt called target=0x%x, pname=0x%x, param=%d", target, pname, param); MG_Util::Debug::LogD("MG_State: Texture: SetTexturePropertyInt called target=0x%x, pname=0x%x, param=%d", target, pname, param);
if (MG_Constants::Texture::VALID_TARGETS.find(target) == MG_Constants::Texture::VALID_TARGETS.end()) { if (!MG_Constants::Common::Contains(target, MG_Constants::Texture::VALID_TARGETS)) {
MG_Util::Debug::LogE("MG_State: Texture: SetTexturePropertyInt invalid target=0x%x", target); MG_Util::Debug::LogE("MG_State: Texture: SetTexturePropertyInt invalid target=0x%x", target);
return GL_INVALID_ENUM; return GL_INVALID_ENUM;
} }
if (MG_Constants::Texture::VALID_TEXTURE_PARAM_NAMES.find(pname) == MG_Constants::Texture::VALID_TEXTURE_PARAM_NAMES.end()) { if (!MG_Constants::Common::Contains(pname, MG_Constants::Texture::VALID_TEXTURE_PARAM_NAMES)) {
MG_Util::Debug::LogE("MG_State: Texture: SetTexturePropertyInt invalid pname=0x%x", pname); MG_Util::Debug::LogE("MG_State: Texture: SetTexturePropertyInt invalid pname=0x%x", pname);
return GL_INVALID_ENUM; return GL_INVALID_ENUM;
} }
@@ -646,7 +641,7 @@ GLenum TextureState::DeleteN(GLsizei n, const GLuint* textures) {
GLenum TextureState::QueryLevelPropertyIntVector(GLenum target, GLint level, GLenum pname, GLint* params) { GLenum TextureState::QueryLevelPropertyIntVector(GLenum target, GLint level, GLenum pname, GLint* params) {
MG_Util::Debug::LogD("MG_State: Texture: QueryLevelPropertyIntVector called target=0x%x, level=%d, pname=0x%x", target, level, pname); MG_Util::Debug::LogD("MG_State: Texture: QueryLevelPropertyIntVector called target=0x%x, level=%d, pname=0x%x", target, level, pname);
if (MG_Constants::Texture::VALID_TARGETS.find(target) == MG_Constants::Texture::VALID_TARGETS.end()) { if (!MG_Constants::Common::Contains(target, MG_Constants::Texture::VALID_TARGETS)) {
MG_Util::Debug::LogE("MG_State: Texture: QueryLevelPropertyIntVector invalid target=0x%x", target); MG_Util::Debug::LogE("MG_State: Texture: QueryLevelPropertyIntVector invalid target=0x%x", target);
return GL_INVALID_ENUM; return GL_INVALID_ENUM;
} }
@@ -656,7 +651,7 @@ GLenum TextureState::QueryLevelPropertyIntVector(GLenum target, GLint level, GLe
return GL_INVALID_VALUE; return GL_INVALID_VALUE;
} }
if (MG_Constants::Texture::VALID_QUERY_LEVEL_PROPERTY_PARAM_NAMES.find(pname) == MG_Constants::Texture::VALID_QUERY_LEVEL_PROPERTY_PARAM_NAMES.end()) { if (!MG_Constants::Common::Contains(pname, MG_Constants::Texture::VALID_TEXTURE_PARAM_NAMES)) {
MG_Util::Debug::LogE("MG_State: Texture: QueryLevelPropertyIntVector invalid pname=0x%x", pname); MG_Util::Debug::LogE("MG_State: Texture: QueryLevelPropertyIntVector invalid pname=0x%x", pname);
return GL_INVALID_ENUM; return GL_INVALID_ENUM;
} }
@@ -700,7 +695,7 @@ GLenum TextureState::QueryLevelPropertyIntVector(GLenum target, GLint level, GLe
return GL_NO_ERROR; return GL_NO_ERROR;
} }
unordered_map<GLuint, TextureObject>::iterator texIt; MG_Global::unordered_map<GLuint, TextureObject>::iterator texIt;
if (!isProxyTexture) { if (!isProxyTexture) {
texIt = textures.find(boundTexture); texIt = textures.find(boundTexture);
@@ -806,7 +801,7 @@ GLenum TextureState::CheckUploadingTexture2DValidity_(GLenum target, GLint level
GLsizei width, GLsizei height, GLint border, GLenum format, GLsizei width, GLsizei height, GLint border, GLenum format,
GLenum type, const void* data) { GLenum type, const void* data) {
MG_Util::Debug::LogD("MG_State: Texture: CheckUploadingTexture2DValidity_ called target=0x%x, level=%d", target, level); MG_Util::Debug::LogD("MG_State: Texture: CheckUploadingTexture2DValidity_ called target=0x%x, level=%d", target, level);
if (MG_Constants::Texture::VALID_TARGETS.find(target) == MG_Constants::Texture::VALID_TARGETS.end()) { if (!MG_Constants::Common::Contains(target, MG_Constants::Texture::VALID_TARGETS)) {
MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity_ invalid target=0x%x", target); MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity_ invalid target=0x%x", target);
return GL_INVALID_ENUM; return GL_INVALID_ENUM;
} }
@@ -846,17 +841,17 @@ GLenum TextureState::CheckUploadingTexture2DValidity_(GLenum target, GLint level
return GL_INVALID_VALUE; return GL_INVALID_VALUE;
} }
if (MG_Constants::Texture::VALID_INTERNAL_FORMATS.find(internalFormat) == MG_Constants::Texture::VALID_INTERNAL_FORMATS.end()) { if (!MG_Constants::Common::Contains((GLenum)internalFormat, MG_Constants::Texture::VALID_INTERNAL_FORMATS)) {
MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity_ invalid internalFormat=0x%x", internalFormat); MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity_ invalid internalFormat=0x%x", internalFormat);
return GL_INVALID_VALUE; return GL_INVALID_VALUE;
} }
if (MG_Constants::Texture::VALID_FORMATS.find(format) == MG_Constants::Texture::VALID_FORMATS.end()) { if (!MG_Constants::Common::Contains((GLenum)format, MG_Constants::Texture::VALID_FORMATS)) {
MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity_ invalid format=0x%x", format); MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity_ invalid format=0x%x", format);
return GL_INVALID_ENUM; return GL_INVALID_ENUM;
} }
if (MG_Constants::Texture::VALID_TYPES.find(type) == MG_Constants::Texture::VALID_TYPES.end()) { if (!MG_Constants::Common::Contains((GLenum)type, MG_Constants::Texture::VALID_TYPES)) {
MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity_ invalid type=0x%x", type); MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity_ invalid type=0x%x", type);
return GL_INVALID_ENUM; return GL_INVALID_ENUM;
} }
@@ -928,7 +923,7 @@ GLenum TextureState::CheckUpdatingTextureRegion2DValidity_(GLenum target, GLint
MG_Util::Debug::LogD("MG_State: Texture: CheckUpdatingTextureRegion2DValidity_ called target=0x%x, level=%d, x=%d, y=%d, w=%d, h=%d", MG_Util::Debug::LogD("MG_State: Texture: CheckUpdatingTextureRegion2DValidity_ called target=0x%x, level=%d, x=%d, y=%d, w=%d, h=%d",
target, level, xoffset, yoffset, width, height); target, level, xoffset, yoffset, width, height);
if (MG_Constants::Texture::VALID_TARGETS.find(target) == MG_Constants::Texture::VALID_TARGETS.end()) { if (!MG_Constants::Common::Contains(target, MG_Constants::Texture::VALID_TARGETS)) {
MG_Util::Debug::LogE("MG_State: Texture: CheckUpdatingTextureRegion2DValidity_ invalid target=0x%x", target); MG_Util::Debug::LogE("MG_State: Texture: CheckUpdatingTextureRegion2DValidity_ invalid target=0x%x", target);
return GL_INVALID_ENUM; return GL_INVALID_ENUM;
} }
@@ -978,12 +973,12 @@ GLenum TextureState::CheckUpdatingTextureRegion2DValidity_(GLenum target, GLint
return GL_INVALID_OPERATION; return GL_INVALID_OPERATION;
} }
if (MG_Constants::Texture::VALID_FORMATS.find(format) == MG_Constants::Texture::VALID_FORMATS.end()) { if (!MG_Constants::Common::Contains(format, MG_Constants::Texture::VALID_FORMATS)) {
MG_Util::Debug::LogE("MG_State: Texture: CheckUpdatingTextureRegion2DValidity_ invalid format=0x%x", format); MG_Util::Debug::LogE("MG_State: Texture: CheckUpdatingTextureRegion2DValidity_ invalid format=0x%x", format);
return GL_INVALID_ENUM; return GL_INVALID_ENUM;
} }
if (MG_Constants::Texture::VALID_TYPES.find(type) == MG_Constants::Texture::VALID_TYPES.end()) { if (!MG_Constants::Common::Contains(type, MG_Constants::Texture::VALID_TYPES)) {
MG_Util::Debug::LogE("MG_State: Texture: CheckUpdatingTextureRegion2DValidity_ invalid type=0x%x", type); MG_Util::Debug::LogE("MG_State: Texture: CheckUpdatingTextureRegion2DValidity_ invalid type=0x%x", type);
return GL_INVALID_ENUM; return GL_INVALID_ENUM;
} }
+11 -20
View File
@@ -4,9 +4,6 @@
#ifndef MOBILEGL_TEXTURESTATE_H #ifndef MOBILEGL_TEXTURESTATE_H
#define MOBILEGL_TEXTURESTATE_H #define MOBILEGL_TEXTURESTATE_H
#define MOBILEGL_GLSTATE_H
#include "../../../Includes.h"
struct ComponentSizes { struct ComponentSizes {
GLint red = 0; GLint red = 0;
@@ -19,10 +16,8 @@ struct ComponentSizes {
}; };
struct TextureParams { struct TextureParams {
template <typename K, typename V> MG_Global::unordered_map<GLenum, GLfloat> texPropertiesFloat;
using unordered_map = ankerl::unordered_dense::map<K, V>; MG_Global::unordered_map<GLenum, GLint> texPropertiesInt;
unordered_map<GLenum, GLfloat> texPropertiesFloat;
unordered_map<GLenum, GLint> texPropertiesInt;
struct MipmapLevel { struct MipmapLevel {
GLsizei width = 0; GLsizei width = 0;
GLsizei height = 0; GLsizei height = 0;
@@ -33,7 +28,7 @@ struct TextureParams {
bool hasData = false; bool hasData = false;
bool dirty = false; // TODO: encapsulate this with an public API to RHI bool dirty = false; // TODO: encapsulate this with an public API to RHI
}; };
unordered_map<GLint, MipmapLevel> mipmapData; MG_Global::unordered_map<GLint, MipmapLevel> mipmapData;
}; };
class TextureObject { class TextureObject {
@@ -47,35 +42,31 @@ public:
}; };
class TextureUnitState { class TextureUnitState {
template <typename K, typename V>
using unordered_map = ankerl::unordered_dense::map<K, V>;
private:
GLenum activeTarget = GL_TEXTURE_2D;
public: public:
unordered_map<GLenum, GLuint> boundTextures;
void Bind(GLenum target, GLuint texture); void Bind(GLenum target, GLuint texture);
GLuint GetBoundTexture(GLenum target); GLuint GetBoundTexture(GLenum target);
GLenum activeTarget = GL_TEXTURE_2D;
MG_Global::unordered_map<GLenum, GLuint> boundTextures;
}; };
class TextureState { class TextureState {
template <typename K, typename V>
using unordered_map = ankerl::unordered_dense::map<K, V>;
private: private:
GLuint lastUsedID_ = 1; GLuint lastUsedID_ = 1;
// ankerl::unordered_set<GLuint> freeIDs_; // MG_Global::unordered_set<GLuint> freeIDs_;
std::vector<GLuint> freeID_; std::vector<GLuint> freeID_;
unordered_map<GLenum, TextureObject> proxyTextures_; MG_Global::unordered_map<GLenum, TextureObject> proxyTextures_;
static GLint GetUnpackParam_(GLenum pname); static GLint GetUnpackParam_(GLenum pname);
public: public:
TextureState(); TextureState();
bool IsTextureGenerated(GLuint texture); bool IsTextureGenerated(GLuint texture);
bool IsTexture(GLuint texture); bool IsTexture(GLuint texture);
unordered_map<GLuint, TextureObject> textures; MG_Global::unordered_map<GLuint, TextureObject> textures;
// Return: the validity of the operation, according to OpenGL 3 standard // Return: the validity of the operation, according to OpenGL 3 standard
GLenum BindUnit(GLenum textureUnit); GLenum BindUnit(GLenum textureUnit);
@@ -4,7 +4,7 @@
// TODO: Add more gl error check for vertex array state manager. // TODO: Add more gl error check for vertex array state manager.
#include "VertexArrayState.h" #include "../../../Includes.h"
VertexArrayState::VertexArrayState() { VertexArrayState::VertexArrayState() {
vaos_[0]; vaos_[0];
@@ -107,7 +107,7 @@ bool VertexArrayState::ValidateAllocatedHandle(GLuint array) {
GLenum VertexArrayState::EnableAttrib(GLuint index) { GLenum VertexArrayState::EnableAttrib(GLuint index) {
if (!ValidateAllocatedHandle(currentVao_)) if (!ValidateAllocatedHandle(currentVao_))
return GL_INVALID_OPERATION; return GL_INVALID_OPERATION;
if (index >= GL_MAX_VERTEX_ATTRIBS) return GL_INVALID_VALUE; if (index >= MG_Constants::VertexArray::MAX_VERTEX_ATTRIBS) return GL_INVALID_VALUE;
GetCurrentVAO()->attribs[index].enabled = true; GetCurrentVAO()->attribs[index].enabled = true;
MG_Util::Debug::LogD("Attrib vaos_[%u].attribs[%u].enabled = %d", currentVao_, index, vaos_[currentVao_].attribs[index].enabled); MG_Util::Debug::LogD("Attrib vaos_[%u].attribs[%u].enabled = %d", currentVao_, index, vaos_[currentVao_].attribs[index].enabled);
@@ -118,7 +118,7 @@ GLenum VertexArrayState::EnableAttrib(GLuint index) {
GLenum VertexArrayState::DisableAttrib(GLuint index) { GLenum VertexArrayState::DisableAttrib(GLuint index) {
if (!ValidateAllocatedHandle(currentVao_)) if (!ValidateAllocatedHandle(currentVao_))
return GL_INVALID_OPERATION; return GL_INVALID_OPERATION;
if (index >= GL_MAX_VERTEX_ATTRIBS) return GL_INVALID_VALUE; if (index >= MG_Constants::VertexArray::MAX_VERTEX_ATTRIBS) return GL_INVALID_VALUE;
GetCurrentVAO()->attribs[index].enabled = false; GetCurrentVAO()->attribs[index].enabled = false;
MG_Util::Debug::LogD("Attrib vaos_[%u].attribs[%u].enabled = %d", currentVao_, index, vaos_[currentVao_].attribs[index].enabled); MG_Util::Debug::LogD("Attrib vaos_[%u].attribs[%u].enabled = %d", currentVao_, index, vaos_[currentVao_].attribs[index].enabled);
@@ -132,7 +132,7 @@ GLenum VertexArrayState::SetAttribPointer(GLuint index, GLint size, GLenum type,
GLuint currentArrayBuffer) { GLuint currentArrayBuffer) {
if (!ValidateAllocatedHandle(currentVao_)) if (!ValidateAllocatedHandle(currentVao_))
return GL_INVALID_OPERATION; return GL_INVALID_OPERATION;
if (index >= GL_MAX_VERTEX_ATTRIBS) return GL_INVALID_VALUE; if (index >= MG_Constants::VertexArray::MAX_VERTEX_ATTRIBS) return GL_INVALID_VALUE;
VertexAttribState state; VertexAttribState state;
state.size = size; state.size = size;
@@ -142,8 +142,7 @@ GLenum VertexArrayState::SetAttribPointer(GLuint index, GLint size, GLenum type,
state.pointer = pointer; state.pointer = pointer;
state.buffer = currentArrayBuffer; state.buffer = currentArrayBuffer;
state.isInteger = isInteger; state.isInteger = isInteger;
if (vaos_[currentVao_].attribs.count(index) && vaos_[currentVao_].attribs[index].enabled) state.enabled = vaos_[currentVao_].attribs[index].enabled;
state.enabled = true;
vaos_[currentVao_].attribs[index] = state; vaos_[currentVao_].attribs[index] = state;
@@ -4,12 +4,9 @@
#ifndef MOBILEGL_VERTEXARRAYSTATE_H #ifndef MOBILEGL_VERTEXARRAYSTATE_H
#define MOBILEGL_VERTEXARRAYSTATE_H #define MOBILEGL_VERTEXARRAYSTATE_H
#define MOBILEGL_GLSTATE_H
#include "../../../Includes.h"
struct VertexAttribState { struct VertexAttribState {
bool enabled; bool enabled = false;
GLint size = 4; GLint size = 4;
GLenum type = GL_FLOAT; GLenum type = GL_FLOAT;
GLboolean normalized = GL_FALSE; GLboolean normalized = GL_FALSE;
@@ -24,7 +21,7 @@ struct VertexArrayObject {
bool attribDirty = false; bool attribDirty = false;
bool eboDirty = false; bool eboDirty = false;
GLuint elementBuffer = 0; GLuint elementBuffer = 0;
ankerl::unordered_map<GLuint, VertexAttribState> attribs; std::array<VertexAttribState, MG_Constants::VertexArray::MAX_VERTEX_ATTRIBS> attribs;
}; };
class VertexArrayState { class VertexArrayState {
@@ -50,7 +47,7 @@ public:
bool ValidateAllocatedHandle(GLuint array); bool ValidateAllocatedHandle(GLuint array);
GLuint currentVao_ = 0; GLuint currentVao_ = 0;
ankerl::unordered_map<GLuint, VertexArrayObject> vaos_; MG_Global::unordered_map<GLuint, VertexArrayObject> vaos_;
private: private:
std::set<GLuint> freeIds_; std::set<GLuint> freeIds_;
GLuint lastId_ = 0; GLuint lastId_ = 0;
+73
View File
@@ -0,0 +1,73 @@
//
// Created by yello on 2025-06-27.
//
#ifndef INDEXGENERATOR_H
#define INDEXGENERATOR_H
#include <vector>
#include <cstddef> // For size_t
#include <algorithm> // For std::min
#include <memory>
template <typename IndexType>
class IndexGenerator {
public:
// 构造函数
IndexGenerator() : next_index_(1) {}
explicit IndexGenerator(IndexType n) : next_index_(1) {
is_valid_.reserve(n);
}
// 生成n个新正整数
void Generate(size_t n, IndexType *indices) {
if (n <= 0) {
return;
}
// 优先给出被删除的索引
size_t count_from_freed = std::min(n, freed_indices_.size());
for (size_t i = 0; i < count_from_freed; ++i) {
indices[i] = freed_indices_.back();
freed_indices_.pop_back();
// 标记为有效,确保is_valid_的大小足够
if (indices[i] >= is_valid_.size()) {
is_valid_.resize(static_cast<size_t>(indices[i]) + 1, false); // 0代表无效,1代表有效
}
is_valid_[indices[i]] = true; // 标记为有效
}
// 如果还需要更多的索引,则生成新的索引
for (size_t i = count_from_freed; i < n; ++i) {
indices[i] = next_index_++;
// 确保is_valid_的大小足够
if (indices[i] >= is_valid_.size()) {
is_valid_.resize(static_cast<size_t>(indices[i]) + 1, false);
}
is_valid_[indices[i]] = true; // 标记为有效
}
}
// 删除一个已经给出的正整数
void Delete(IndexType index) {
// 检查索引是否有效且未被删除
// 这里的检查是为了避免重复删除或删除未生成的索引
if (index < is_valid_.size() && is_valid_[index] == true) {
is_valid_[index] = false; // 标记为无效
freed_indices_.push_back(index); // 添加到已删除列表中
}
}
// 检查一个正整数是否之前已经被给出,并且没有被删除
bool IsValid(IndexType index) const {
// 如果索引超出is_valid_的范围,或者对应的位置是0,则认为无效
return index < is_valid_.size() && is_valid_[index] == true;
}
private:
IndexType next_index_; // 下一个将要生成的正整数
std::vector<IndexType> freed_indices_; // 存储被删除的索引
std::vector<bool> is_valid_; // 标记索引是否有效。0代表无效,1代表有效。
};
#endif //INDEXGENERATOR_H
+9 -3
View File
@@ -2,7 +2,7 @@
// Created by BZLZHH on 2025/4/26. // Created by BZLZHH on 2025/4/26.
// //
#include "TestDrawing.h" #include "../../../Includes.h"
namespace MG_RHI::GLES::Test { namespace MG_RHI::GLES::Test {
constexpr int DISPLAY_COLUMNS = 8; constexpr int DISPLAY_COLUMNS = 8;
@@ -14,6 +14,7 @@ namespace MG_RHI::GLES::Test {
} }
bool CheckShaderCompileStatus(GLuint shader, const char* type) { bool CheckShaderCompileStatus(GLuint shader, const char* type) {
#if BACKEND_TYPE == BACKEND_GLES
GLint success; GLint success;
::GLES::glGetShaderiv(shader, GL_COMPILE_STATUS, &success); ::GLES::glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (!success) { if (!success) {
@@ -22,10 +23,12 @@ namespace MG_RHI::GLES::Test {
MG_Util::Debug::LogE("Shader compilation error (%s): %s", type, infoLog); MG_Util::Debug::LogE("Shader compilation error (%s): %s", type, infoLog);
return false; return false;
} }
#endif
return true; return true;
} }
bool CheckProgramLinkStatus(GLuint program) { bool CheckProgramLinkStatus(GLuint program) {
#if BACKEND_TYPE == BACKEND_GLES
GLint success; GLint success;
::GLES::glGetProgramiv(program, GL_LINK_STATUS, &success); ::GLES::glGetProgramiv(program, GL_LINK_STATUS, &success);
if (!success) { if (!success) {
@@ -34,11 +37,13 @@ namespace MG_RHI::GLES::Test {
MG_Util::Debug::LogE("Program link error: %s", infoLog); MG_Util::Debug::LogE("Program link error: %s", infoLog);
return false; return false;
} }
#endif
return true; return true;
} }
// TODO: Use the textures state from MG_RHI(another state?) rather than directly from MG_State // TODO: Use the textures state from MG_RHI(another state?) rather than directly from MG_State
void DrawAllTextures() { void DrawAllTextures() {
#if BACKEND_TYPE == BACKEND_GLES
::GLES::glClearColor(1,1,1,1); ::GLES::glClearColor(1,1,1,1);
::GLES::glClear(GL_COLOR_BUFFER_BIT); ::GLES::glClear(GL_COLOR_BUFFER_BIT);
@@ -48,8 +53,8 @@ namespace MG_RHI::GLES::Test {
GLuint quadVBO = 0; GLuint quadVBO = 0;
GLint uTexLoc = -1; GLint uTexLoc = -1;
GLint uMVPLoc = -1; GLint uMVPLoc = -1;
ankerl::unordered_map<GLuint, GLuint> textureCache; MG_Global::unordered_map<GLuint, GLuint> textureCache;
ankerl::unordered_map<GLuint, bool> textureDirty; MG_Global::unordered_map<GLuint, bool> textureDirty;
}; };
static ScreenResources sRes; static ScreenResources sRes;
@@ -230,5 +235,6 @@ namespace MG_RHI::GLES::Test {
::GLES::glUseProgram(origProgram); ::GLES::glUseProgram(origProgram);
::GLES::glViewport(origViewport[0], origViewport[1], ::GLES::glViewport(origViewport[0], origViewport[1],
origViewport[2], origViewport[3]); origViewport[2], origViewport[3]);
#endif
} }
} }
-2
View File
@@ -5,8 +5,6 @@
#ifndef MOBILEGL_TESTDRAWING_H #ifndef MOBILEGL_TESTDRAWING_H
#define MOBILEGL_TESTDRAWING_H #define MOBILEGL_TESTDRAWING_H
#include "../../../Includes.h"
namespace MG_RHI::GLES::Test { namespace MG_RHI::GLES::Test {
void DrawAllTextures(); void DrawAllTextures();
} }
+1792 -1033
View File
File diff suppressed because it is too large Load Diff
+1 -2
View File
@@ -5,8 +5,6 @@
#ifndef MOBILEGL_DEBUG_H #ifndef MOBILEGL_DEBUG_H
#define MOBILEGL_DEBUG_H #define MOBILEGL_DEBUG_H
#include "../../Includes.h"
#define FORCE_SYNC_WITH_LOG_FILE 0 #define FORCE_SYNC_WITH_LOG_FILE 0
namespace MG_Util { namespace MG_Util {
@@ -23,6 +21,7 @@ namespace MG_Util {
void LogWrite(const char* format, va_list args); void LogWrite(const char* format, va_list args);
const char* GLEnumToString(::GLenum value); const char* GLEnumToString(::GLenum value);
const char* DiligentBlendFactorToString(Diligent::BLEND_FACTOR value);
} }
} }
+7 -8
View File
@@ -2,7 +2,7 @@
// Created by BZLZHH on 2025/5/3. // Created by BZLZHH on 2025/5/3.
// //
#include "DebugTool.h" #include "../../Includes.h"
namespace MG_Util::Program { namespace MG_Util::Program {
std::string GLTypeToString(GLenum type) { std::string GLTypeToString(GLenum type) {
@@ -54,7 +54,7 @@ namespace MG_Util::Program {
std::ostringstream ss; std::ostringstream ss;
ss << "["; ss << "[";
const size_t elemCount = std::min<size_t>(value.count, 16); const size_t elemCount = std::min<size_t>(value.numElements, 16);
switch(value.type) { switch(value.type) {
case GL_FLOAT: case GL_FLOAT:
@@ -116,17 +116,17 @@ namespace MG_Util::Program {
} }
void DumpUniforms(const ProgramState& state, GLuint program) { void DumpUniforms(const ProgramState& state, GLuint program) {
if (MG_Global::Common::LogLevel > MG_Constants::Common::LOG_LEVEL_DEBUG) if constexpr (MG_Global::Common::LogLevel > MG_Constants::Common::LOG_LEVEL_DEBUG)
return; return;
auto prog = (ProgramObject)state.GetProgramObject(program); auto* prog = state.GetProgramObject(program);
if (!prog.linked.toBool()) { if (!prog->linked.toBool()) {
MG_Util::Debug::LogE("Program %u not linked", program); MG_Util::Debug::LogE("Program %u not linked", program);
return; return;
} }
MG_Util::Debug::LogD("=== Dumping uniforms for program %u ===", program); MG_Util::Debug::LogD("=== Dumping uniforms for program %u ===", program);
for(const auto& [name, loc] : prog.uniformLocations) { for(const auto& [name, loc] : prog->uniformLocations) {
const auto& value = prog.uniformValues.at(name); const auto& value = prog->uniformValues.at(name);
MG_Util::Debug::LogD("Uniform: %-24s Location: %-4d Type: %-16s Count: %-3d Value: %s", MG_Util::Debug::LogD("Uniform: %-24s Location: %-4d Type: %-16s Count: %-3d Value: %s",
name.c_str(), name.c_str(),
loc, loc,
@@ -142,7 +142,6 @@ namespace MG_Util::Program {
GLuint current = state.GetCurrentProgram(); GLuint current = state.GetCurrentProgram();
if (current == 0) { if (current == 0) {
MG_Util::Debug::LogE("No active program");
return; return;
} }
DumpUniforms(state, current); DumpUniforms(state, current);
-1
View File
@@ -4,7 +4,6 @@
#ifndef MOBILEGL_PROGRAM_DEBUGTOOL_H #ifndef MOBILEGL_PROGRAM_DEBUGTOOL_H
#define MOBILEGL_PROGRAM_DEBUGTOOL_H #define MOBILEGL_PROGRAM_DEBUGTOOL_H
#include "../../Includes.h"
namespace MG_Util::Program { namespace MG_Util::Program {
std::string GLTypeToString(GLenum type); std::string GLTypeToString(GLenum type);
+749 -25
View File
@@ -2,10 +2,666 @@
// Created by BZLZHH on 2025/5/3. // Created by BZLZHH on 2025/5/3.
// //
#include "GLSLTool.h" #include "../../Includes.h"
namespace MG_Util::Program { namespace MG_Util::Program {
std::string CompileGLSLToTShader(GLenum shaderType, const std::string& source, glslang::TShader *&shader) { void RenameGLSLBuiltinsForVulkan(std::string &src) {
// static const std::vector<std::pair<std::regex, std::string>> rules = {
// { std::regex(R"(gl_VertexID)"), "gl_VertexIndex" },
// { std::regex(R"(gl_InstanceID)"), "gl_InstanceIndex" }
// };
//
// for (auto &rule : rules) {
// src = std::regex_replace(src, rule.first, rule.second);
// }
size_t pos = src.find("gl_VertexID");
if (pos != std::string::npos) {
src.replace(pos, strlen("gl_VertexID"), "gl_VertexIndex");
}
pos = src.find("gl_InstanceID");
if (pos != std::string::npos) {
src.replace(pos, strlen("gl_InstanceID"), "gl_InstanceIndex");
}
}
std::string BindInputLayoutLocationsForGLSL(
std::vector<uint32_t>& spirv,
MG_Global::unordered_map<std::string, GLint>& name_location_map)
{
spvc_context context = nullptr;
spvc_parsed_ir ir = nullptr;
spvc_compiler compiler = nullptr;
spvc_resources resources = nullptr;
spvc_result result = SPVC_SUCCESS;
const char* glsl_source = nullptr;
std::string output_glsl;
if ((result = spvc_context_create(&context)) != SPVC_SUCCESS)
{
MG_Util::Debug::LogE("[SPIRV-Cross] Failed to create context.");
return {};
}
if ((result = spvc_context_parse_spirv(context,
spirv.data(),
spirv.size(),
&ir)) != SPVC_SUCCESS)
{
spvc_context_destroy(context);
MG_Util::Debug::LogE("[SPIRV-Cross] Failed to parse SPIR-V.");
return {};
}
if ((result = spvc_context_create_compiler(
context,
SPVC_BACKEND_GLSL,
ir,
SPVC_CAPTURE_MODE_TAKE_OWNERSHIP,
&compiler)) != SPVC_SUCCESS)
{
spvc_context_destroy(context);
MG_Util::Debug::LogE("[SPIRV-Cross] Failed to create compiler.");
return {};
}
if ((result = spvc_compiler_create_shader_resources(compiler, &resources)) != SPVC_SUCCESS)
{
spvc_context_destroy(context);
MG_Util::Debug::LogE("[SPIRV-Cross] Failed to create shader resources.");
return {};
}
const spvc_reflected_resource* inputs = nullptr;
size_t num_inputs = 0;
if ((result = spvc_resources_get_resource_list_for_type(
resources,
SPVC_RESOURCE_TYPE_STAGE_INPUT,
&inputs,
&num_inputs)) != SPVC_SUCCESS)
{
spvc_context_destroy(context);
MG_Util::Debug::LogE("[SPIRV-Cross] Failed to get stage inputs.");
return {};
}
std::unordered_map<std::string, spvc_variable_id> name_to_id;
for (size_t i = 0; i < num_inputs; ++i)
{
name_to_id[inputs[i].name] = inputs[i].id;
}
std::unordered_set<GLint> used_locations;
for (auto& kv : name_location_map)
{
const auto& name = kv.first;
GLint loc = kv.second;
auto it = name_to_id.find(name);
if (it == name_to_id.end())
{
MG_Util::Debug::LogW("[SPIRV-Cross] Input name not found: %s", name.c_str());
continue;
}
spvc_compiler_set_decoration(
compiler,
it->second,
SpvDecorationLocation,
loc);
used_locations.insert(loc);
}
GLint next_free_loc = 0;
for (size_t i = 0; i < num_inputs; ++i)
{
auto& res = inputs[i];
const auto& name = res.name;
auto var_id = res.id;
if (name_location_map.find(name) != name_location_map.end())
continue;
uint32_t curr_loc = 0;
bool has_loc = false;
curr_loc = spvc_compiler_get_decoration(compiler, var_id, SpvDecorationLocation);
if (spvc_compiler_has_decoration(compiler, var_id, SpvDecorationLocation))
has_loc = true;
if (has_loc && !used_locations.contains(curr_loc))
{
used_locations.insert((GLint)curr_loc);
continue;
}
while (used_locations.count(next_free_loc))
++next_free_loc;
spvc_compiler_set_decoration(
compiler,
var_id,
SpvDecorationLocation,
next_free_loc);
MG_Util::Debug::LogI("[SPIRV-Cross] Auto assigned '%s' to location %d", name, next_free_loc);
used_locations.insert(next_free_loc);
}
spvc_compiler_options options = nullptr;
spvc_compiler_create_compiler_options(compiler, &options);
spvc_compiler_options_set_uint(options, SPVC_COMPILER_OPTION_GLSL_VERSION, 450);
spvc_compiler_options_set_bool(options, SPVC_COMPILER_OPTION_GLSL_ES, SPVC_FALSE);
spvc_compiler_options_set_bool(options, SPVC_COMPILER_OPTION_FLIP_VERTEX_Y, SPVC_TRUE);
spvc_compiler_install_compiler_options(compiler, options);
if ((result = spvc_compiler_compile(compiler, &glsl_source)) != SPVC_SUCCESS)
{
MG_Util::Debug::LogE("[SPIRV-Cross] Failed to compile: %s",
spvc_context_get_last_error_string(context));
spvc_context_destroy(context);
return {};
}
output_glsl = glsl_source;
spvc_context_destroy(context);
MG_Util::Debug::LogI("[SPIRV-Cross] GLSL output:\n%s", output_glsl.c_str());
size_t pos = output_glsl.find("\n gl_Position.y = -gl_Position.y;\n}");
if (pos != std::string::npos)
{
output_glsl.replace(
pos,
strlen("\n gl_Position.y = -gl_Position.y;\n}"),
"\n gl_Position.y = -gl_Position.y;\n gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n}");
}
return output_glsl;
}
static std::vector<bool> buildCommentMask(const std::string &src) {
enum State {
NORMAL,
LINE_COMMENT,
BLOCK_COMMENT,
STRING_LITERAL,
CHAR_LITERAL
};
std::vector<bool> isComment(src.size(), false);
State state = NORMAL;
for (size_t i = 0; i < src.size(); ++i) {
switch (state) {
case NORMAL:
if (i + 1 < src.size() && src[i] == '/' && src[i + 1] == '/') {
state = LINE_COMMENT;
isComment[i] = true;
isComment[i + 1] = true;
++i;
}
else if (i + 1 < src.size() && src[i] == '/' && src[i + 1] == '*') {
state = BLOCK_COMMENT;
isComment[i] = true;
isComment[i + 1] = true;
++i;
}
else if (src[i] == '"') {
state = STRING_LITERAL;
}
else if (src[i] == '\'') {
state = CHAR_LITERAL;
}
break;
case LINE_COMMENT:
isComment[i] = true;
if (src[i] == '\n') {
state = NORMAL;
}
break;
case BLOCK_COMMENT:
isComment[i] = true;
if (i + 1 < src.size() && src[i] == '*' && src[i + 1] == '/') {
isComment[i + 1] = true;
state = NORMAL;
++i;
}
break;
case STRING_LITERAL:
if (src[i] == '\\' && (i + 1 < src.size())) {
i++;
}
else if (src[i] == '"') {
state = NORMAL;
}
break;
case CHAR_LITERAL:
if (src[i] == '\\' && (i + 1 < src.size())) {
i++;
}
else if (src[i] == '\'') {
state = NORMAL;
}
break;
}
}
return isComment;
}
static bool isPreprocessorLine(const std::string &src, size_t pos) {
size_t lineStart = src.rfind('\n', pos);
if (lineStart == std::string::npos) {
lineStart = 0;
} else {
lineStart += 1;
}
size_t firstNonSpace = src.find_first_not_of(" \t\r\n", lineStart);
if (firstNonSpace != std::string::npos && src[firstNonSpace] == '#') {
return true;
}
return false;
}
static inline bool isInComment(const std::vector<bool> &mask, size_t pos) {
if (pos >= mask.size()) return false;
return mask[pos];
}
static inline void leftTrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) {
return !std::isspace(ch);
}));
}
static inline void rightTrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
return !std::isspace(ch);
}).base(), s.end());
}
static inline void trim(std::string &s) {
leftTrim(s);
rightTrim(s);
}
static size_t findNextNonSpace(const std::string& str, size_t pos) {
return str.find_first_not_of(" \t\r\n", pos);
}
static std::string extractVarNameFromUniformDecl(const std::string& decl) {
const std::regex layoutRegex(R"(\s*layout\s*\([^)]*\))");
std::string declNoLayout = std::regex_replace(decl, layoutRegex, "");
size_t uniformPos = declNoLayout.find("uniform");
if (uniformPos != std::string::npos) {
declNoLayout = declNoLayout.substr(uniformPos + 7);
}
trim(declNoLayout);
size_t semiPos = declNoLayout.rfind(';');
if (semiPos != std::string::npos) {
declNoLayout = declNoLayout.substr(0, semiPos);
}
trim(declNoLayout);
size_t lastSpace = declNoLayout.find_last_of(" \t\r\n");
if (lastSpace == std::string::npos) {
return declNoLayout;
}
std::string candidate = declNoLayout.substr(lastSpace + 1);
size_t bracketPos = candidate.find('[');
if (bracketPos != std::string::npos) {
candidate = candidate.substr(0, bracketPos);
}
return candidate;
}
std::pair<std::string, std::string> GenerateDefaultUBOForGLSL(const std::pair<std::string,
std::string>& glslSources) {
std::string source1 = glslSources.first;
std::string source2 = glslSources.second;
std::vector<bool> commentMask1 = buildCommentMask(source1);
std::vector<bool> commentMask2 = buildCommentMask(source2);
const std::regex layoutRegex(R"(\s*layout\s*\([^)]*\))");
std::set<std::string> allUniformNames;
std::vector<std::string> mergedUniforms;
std::vector<std::pair<size_t, size_t>> removalSpans1;
std::vector<std::pair<size_t, size_t>> removalSpans2;
auto processSource = [&](std::string& source, const std::vector<bool>& commentMask,
std::vector<std::pair<size_t, size_t>>& removalSpans,
bool isFirstSource)
{
size_t searchPos = 0;
while ((searchPos = source.find("uniform", searchPos)) != std::string::npos) {
if (isInComment(commentMask, searchPos)) {
searchPos++;
continue;
}
if (isPreprocessorLine(source, searchPos)) {
searchPos++;
continue;
}
if (searchPos > 0 && (std::isalnum(source[searchPos - 1]) || source[searchPos - 1] == '_')) {
searchPos++;
continue;
}
size_t nextCharPos = findNextNonSpace(source, searchPos + 7);
if (nextCharPos == std::string::npos) break;
if (source[nextCharPos] == '{') {
searchPos = nextCharPos + 1;
continue;
}
size_t bracePos = source.find('{', nextCharPos);
size_t semicolonPos = source.find(';', nextCharPos);
if (bracePos != std::string::npos && (semicolonPos == std::string::npos || bracePos < semicolonPos)) {
searchPos = bracePos + 1;
continue;
}
if (semicolonPos == std::string::npos) {
searchPos++;
continue;
}
size_t declStart = searchPos;
size_t declLength = semicolonPos - searchPos + 1;
std::string declaration = source.substr(declStart, declLength);
std::string declNoLayout = std::regex_replace(declaration, layoutRegex, "");
std::string afterUniform = declNoLayout.substr(declNoLayout.find("uniform") + 7);
trim(afterUniform);
size_t sep = afterUniform.find_first_of(" \t\r\n[");
std::string typeToken = (sep == std::string::npos ? afterUniform : afterUniform.substr(0, sep));
bool isSamplerOrImage = false;
if (typeToken.rfind("sampler", 0) == 0 ||
typeToken.rfind("isampler", 0) == 0 ||
typeToken.rfind("usampler", 0) == 0 ||
typeToken.rfind("image", 0) == 0)
{
isSamplerOrImage = true;
}
if (isSamplerOrImage) {
searchPos = declStart + declLength;
continue;
}
std::string varName = extractVarNameFromUniformDecl(declaration);
if (isFirstSource) {
mergedUniforms.push_back(declaration);
allUniformNames.insert(varName);
} else {
if (allUniformNames.find(varName) == allUniformNames.end()) {
mergedUniforms.push_back(declaration);
allUniformNames.insert(varName);
}
}
size_t removeStart = declStart;
{
size_t scanBack = declStart;
while (scanBack > 0 && std::isspace((unsigned char)source[scanBack - 1])) {
scanBack--;
}
if (scanBack >= 6) {
size_t maybeLayout = source.rfind("layout", scanBack - 6);
if (maybeLayout != std::string::npos) {
size_t parenOpen = source.find('(', maybeLayout + 6);
if (parenOpen != std::string::npos && parenOpen < scanBack) {
size_t parenClose = source.find(')', parenOpen);
if (parenClose != std::string::npos && parenClose < declStart) {
std::string between = source.substr(maybeLayout, declStart - maybeLayout);
const std::regex onlyLayout(R"(layout\s*\([^)]*\)\s*)");
if (std::regex_match(between, onlyLayout)) {
removeStart = maybeLayout;
}
}
}
}
}
}
removalSpans.emplace_back(removeStart, (declStart + declLength) - removeStart);
searchPos = declStart + declLength;
}
};
processSource(source1, commentMask1, removalSpans1, true);
processSource(source2, commentMask2, removalSpans2, false);
if (mergedUniforms.empty()) {
return glslSources;
}
std::sort(removalSpans1.rbegin(), removalSpans1.rend());
for (auto &span : removalSpans1) {
source1.erase(span.first, span.second);
}
source1 = std::regex_replace(source1, std::regex(R"((\r\n|\n|\r){2,})"), "$1");
std::sort(removalSpans2.rbegin(), removalSpans2.rend());
for (auto &span : removalSpans2) {
source2.erase(span.first, span.second);
}
source2 = std::regex_replace(source2, std::regex(R"((\r\n|\n|\r){2,})"), "$1");
std::string uboBlock = "\nlayout(std140) uniform MG_DEFAULT_UBO\n{\n";
for (auto &decl : mergedUniforms) {
std::string cleaned = std::regex_replace(decl, layoutRegex, "");
std::string memberDecl = cleaned.substr(cleaned.find("uniform") + 7);
size_t semiPos = memberDecl.rfind(';');
if (semiPos != std::string::npos) {
memberDecl.erase(semiPos);
}
trim(memberDecl);
uboBlock += " " + memberDecl + ";\n";
}
uboBlock += "};\n";
auto insertUBO = [&](std::string& source) {
size_t insertPos = 0, lastDirectivePos = 0;
size_t searchPos = 0;
while ((searchPos = source.find('#', searchPos)) != std::string::npos) {
if (isInComment(commentMask1, searchPos)) {
searchPos++;
continue;
}
size_t eol = source.find('\n', searchPos);
if (eol == std::string::npos) break;
std::string line = source.substr(searchPos, eol - searchPos);
if (line.find("#version") != std::string::npos || line.find("#extension") != std::string::npos) {
lastDirectivePos = eol + 1;
}
searchPos = eol + 1;
}
insertPos = lastDirectivePos;
source.insert(insertPos, uboBlock);
};
insertUBO(source1);
insertUBO(source2);
return {source1, source2};
}
void GenerateDefaultUBOForGLSL_Multi(
MG_Global::unordered_map<GLuint, std::string> &shaderSources, std::vector<std::string>& outUniformBufferNames) {
if (shaderSources.empty()) return;
outUniformBufferNames.clear();
std::unordered_map<GLuint, std::vector<bool>> commentMasks;
for (auto const& [id, source] : shaderSources) {
commentMasks[id] = buildCommentMask(source);
}
const std::regex layoutRegex(R"(\s*layout\s*\([^)]*\))");
std::set<std::string> allUniformNames;
std::vector<std::string> mergedUniforms;
std::unordered_map<GLuint, std::vector<std::pair<size_t, size_t>>> removalSpansPerShader;
for (auto& [id, source] : shaderSources) {
std::vector<bool>& commentMask = commentMasks[id];
// Ensure an entry exists for this shader ID, even if no uniforms are found
auto& removalSpans = removalSpansPerShader[id];
size_t searchPos = 0;
while ((searchPos = source.find("uniform", searchPos)) != std::string::npos) {
if (isInComment(commentMask, searchPos)) {
searchPos++;
continue;
}
if (isPreprocessorLine(source, searchPos)) {
searchPos++;
continue;
}
if (searchPos > 0 && (std::isalnum(source[searchPos - 1]) ||
source[searchPos - 1] == '_')) {
searchPos++;
continue;
}
size_t nextCharPos = findNextNonSpace(source, searchPos + 7);
if (nextCharPos == std::string::npos) break;
if (source[nextCharPos] == '{') {
searchPos = nextCharPos + 1;
continue;
}
size_t bracePos = source.find('{', nextCharPos);
size_t semicolonPos = source.find(';', nextCharPos);
if (bracePos != std::string::npos &&
(semicolonPos == std::string::npos || bracePos < semicolonPos)) {
searchPos = bracePos + 1;
continue;
}
if (semicolonPos == std::string::npos) {
searchPos++;
continue;
}
size_t declStart = searchPos;
size_t declLength = semicolonPos - searchPos + 1;
std::string declaration = source.substr(declStart, declLength);
std::string declNoLayout = std::regex_replace(declaration, layoutRegex, "");
std::string afterUniform = declNoLayout.substr(declNoLayout.find("uniform") + 7);
trim(afterUniform);
size_t sep = afterUniform.find_first_of(" \t\r\n[");
std::string typeToken = (sep == std::string::npos ? afterUniform : afterUniform.substr(0, sep));
bool isSamplerOrImage =
typeToken.rfind("sampler", 0) == 0 ||
typeToken.rfind("isampler", 0) == 0 ||
typeToken.rfind("usampler", 0) == 0 ||
typeToken.rfind("image", 0) == 0;
if (isSamplerOrImage) {
searchPos = declStart + declLength;
continue;
}
std::string varName = extractVarNameFromUniformDecl(declaration);
if (allUniformNames.find(varName) == allUniformNames.end()) {
mergedUniforms.push_back(declaration);
allUniformNames.insert(varName);
// save the uniform names in order
outUniformBufferNames.emplace_back(varName);
}
size_t removeStart = declStart;
size_t scanBack = declStart;
while (scanBack > 0 && std::isspace(static_cast<unsigned char>(source[scanBack - 1]))) {
scanBack--;
}
if (scanBack >= 6) {
size_t maybeLayout = source.rfind("layout", scanBack - 6);
if (maybeLayout != std::string::npos) {
size_t parenOpen = source.find('(', maybeLayout + 6);
if (parenOpen != std::string::npos && parenOpen < scanBack) {
size_t parenClose = source.find(')', parenOpen);
if (parenClose != std::string::npos && parenClose < declStart) {
std::string between = source.substr(maybeLayout, declStart - maybeLayout);
const std::regex onlyLayout(R"(layout\s*\([^)]*\)\s*)");
if (std::regex_match(between, onlyLayout)) {
removeStart = maybeLayout;
}
}
}
}
}
removalSpans.emplace_back(removeStart, (declStart + declLength) - removeStart);
searchPos = declStart + declLength;
}
}
if (mergedUniforms.empty()) return;
for (auto& [id, source] : shaderSources) {
auto& removalSpans = removalSpansPerShader[id];
std::sort(removalSpans.rbegin(), removalSpans.rend());
for (auto& span : removalSpans) {
source.erase(span.first, span.second);
}
}
std::string uboBlock = "\nlayout(std140) uniform MG_DEFAULT_UBO\n{\n";
for (auto& decl : mergedUniforms) {
std::string cleaned = std::regex_replace(decl, layoutRegex, "");
std::string memberDecl = cleaned.substr(cleaned.find("uniform") + 7);
size_t semiPos = memberDecl.rfind(';');
if (semiPos != std::string::npos) {
memberDecl.erase(semiPos);
}
trim(memberDecl);
uboBlock += " " + memberDecl + ";\n";
}
uboBlock += "};\n";
MG_Util::Debug::LogD("UBO Generated:\n%s", uboBlock.c_str());
for (auto& [id, source] : shaderSources) {
size_t insertPos = 0, lastDirectivePos = 0;
size_t searchPos = 0;
while ((searchPos = source.find('#', searchPos)) != std::string::npos) {
if (isInComment(commentMasks[id], searchPos)) {
searchPos++;
continue;
}
size_t eol = source.find('\n', searchPos);
if (eol == std::string::npos) break;
std::string line = source.substr(searchPos, eol - searchPos);
if (line.find("#version") != std::string::npos ||
line.find("#extension") != std::string::npos) {
lastDirectivePos = eol + 1;
}
searchPos = eol + 1;
}
insertPos = lastDirectivePos;
source.insert(insertPos, uboBlock);
}
}
std::string CompileGLSLToTShader(GLenum shaderType, const std::string& source,
glslang::TShader *&shader, bool isVkGLSL) {
std::string infoLog; std::string infoLog;
using namespace glslang; using namespace glslang;
@@ -21,8 +677,12 @@ namespace MG_Util::Program {
shader = new TShader(language); shader = new TShader(language);
const char *src = source.c_str(); const char *src = source.c_str();
shader->setStrings(&src, 1); shader->setStrings(&src, 1);
if (isVkGLSL) {
shader->setPreamble("#define gl_VertexID gl_VertexIndex\n"
"#define gl_InstanceID gl_InstanceIndex\n");
}
shader->setEnvInput(EShSourceGlsl, language, EShClientVulkan, glslVersion); shader->setEnvInput(EShSourceGlsl, language, EShClientVulkan, glslVersion);
shader->setEnvClient(EShClientOpenGL, EShTargetOpenGL_450); shader->setEnvClient(EShClientOpenGL, isVkGLSL ? EShTargetVulkan_1_3 : EShTargetOpenGL_450);
shader->setEnvTarget(EShTargetSpv, EShTargetSpv_1_6); shader->setEnvTarget(EShTargetSpv, EShTargetSpv_1_6);
shader->setAutoMapLocations(true); shader->setAutoMapLocations(true);
shader->setAutoMapBindings(true); shader->setAutoMapBindings(true);
@@ -30,7 +690,7 @@ namespace MG_Util::Program {
// Is InitResources() really correct? // Is InitResources() really correct?
TBuiltInResource resources = InitResources(); TBuiltInResource resources = InitResources();
if (!shader->parse(&resources, glslVersion, true, EShMsgDefault)) { if (!shader->parse(&resources, glslVersion, true, isVkGLSL ? EShMsgVulkanRules : EShMsgDefault)) {
infoLog += "Error: [glslang] Cannot compile the " + GetShaderTypeName(shaderType) + ":\n" infoLog += "Error: [glslang] Cannot compile the " + GetShaderTypeName(shaderType) + ":\n"
+ std::to_string(shader->getInfoLog()); + std::to_string(shader->getInfoLog());
return infoLog; return infoLog;
@@ -45,12 +705,12 @@ namespace MG_Util::Program {
std::vector<EShLanguage> usedShaderTypes; std::vector<EShLanguage> usedShaderTypes;
TProgram program; TProgram program;
for (GLuint shaderId : prog.attachedShaders) { for (GLuint shaderId : prog.attachedShaders) {
auto shaderObject = state.GetShaderObject(shaderId); auto* shaderObject = state.GetShaderObject(shaderId);
EShLanguage shLanguage = GetEShLanguageByShaderType(shaderObject.type); EShLanguage shLanguage = GetEShLanguageByShaderType(shaderObject->type);
TShader* shader = nullptr; TShader* shader = nullptr;
std::string infoLogOfShader = CompileGLSLToTShader(shaderObject.type, shaderObject.source, shader); std::string infoLogOfShader = CompileGLSLToTShader(shaderObject->type, shaderObject->source, shader);
if (!infoLogOfShader.empty()) { if (!infoLogOfShader.empty()) {
infoLog = "Error: [glslang] Cannot compile " + GetShaderTypeName(shaderObject.type) + infoLog = "Error: [glslang] Cannot compile " + GetShaderTypeName(shaderObject->type) +
" :\n" + infoLogOfShader; " :\n" + infoLogOfShader;
return {}; return {};
} }
@@ -62,6 +722,21 @@ namespace MG_Util::Program {
return {}; return {};
} }
std::unique_ptr<glslang::TIoMapResolver> resolver;
for (unsigned stage = 0; stage < EShLangCount; stage++) {
auto* pResolver = program.getGlslIoResolver((EShLanguage)stage);
if (pResolver) {
resolver = std::unique_ptr<glslang::TIoMapResolver>(pResolver);
break;
}
}
auto ioMapper = std::unique_ptr<glslang::TIoMapper>(glslang::GetGlslIoMapper());
if (!program.mapIO(resolver.get(), ioMapper.get())) {
infoLog = "Error: [glslang] Cannot mapIO:\n" + std::to_string(program.getInfoLog());
return {};
}
SpvOptions spvOptions; SpvOptions spvOptions;
spvOptions.disableOptimizer = false; spvOptions.disableOptimizer = false;
@@ -75,21 +750,40 @@ namespace MG_Util::Program {
return allSpirv; return allSpirv;
} }
std::vector<unsigned> CompileGLSLToSPIRV(GLenum shaderType, const std::string &source, std::string &infoLog) { std::vector<unsigned> CompileGLSLToSPIRV(GLenum shaderType, const std::string &source,
std::string &infoLog, bool isVkGLSL, GLenum additionalShaderType,
const std::string& additionalShaderSource
) {
using namespace glslang; using namespace glslang;
TShader* shader = nullptr; TShader* shader = nullptr;
std::string infoLogOfShader = CompileGLSLToTShader(shaderType, source, shader); std::string infoLogOfShader = CompileGLSLToTShader(shaderType, source, shader, isVkGLSL);
if (!infoLogOfShader.empty()) { if (!infoLogOfShader.empty()) {
infoLog = "Error: [glslang] Cannot compile " + GetShaderTypeName(shaderType) + ":\n" + infoLogOfShader; infoLog = "Error: [glslang] Cannot compile " + GetShaderTypeName(shaderType) + ":\n" + infoLogOfShader;
return {}; return {};
} }
TProgram program; TProgram program;
program.addShader(shader);
if (!program.link(EShMsgDefault)) { if (additionalShaderType == GL_VERTEX_SHADER)
program.addShader(shader);
if (additionalShaderType && !additionalShaderSource.empty()) {
TShader* additionalShader = nullptr;
std::string additionalInfoLog = CompileGLSLToTShader(additionalShaderType, additionalShaderSource, additionalShader, isVkGLSL);
if (!additionalInfoLog.empty()) {
infoLog = "Error: [glslang] Cannot compile additional " + GetShaderTypeName(additionalShaderType) + ":\n" + additionalInfoLog;
return {};
}
program.addShader(additionalShader);
}
if (additionalShaderType != GL_VERTEX_SHADER)
program.addShader(shader);
if (!program.link(isVkGLSL ? EShMsgVulkanRules : EShMsgDefault)) {
infoLog = "Error: [glslang] Cannot link the program of the single shader:\n" + std::to_string(program.getInfoLog()); infoLog = "Error: [glslang] Cannot link the program of the single shader:\n" + std::to_string(program.getInfoLog());
return {}; return {};
} }
program.mapIO();
std::vector<unsigned> spirv; std::vector<unsigned> spirv;
SpvOptions spvOptions; SpvOptions spvOptions;
@@ -108,7 +802,7 @@ namespace MG_Util::Program {
return; return;
} }
ankerl::unordered_set<GLint> used_locations; MG_Global::unordered_set<GLint> used_locations;
GLint auto_location = 0; GLint auto_location = 0;
for (auto spirv: allSpirv) { for (auto spirv: allSpirv) {
spvc_parsed_ir ir = nullptr; spvc_parsed_ir ir = nullptr;
@@ -164,15 +858,47 @@ namespace MG_Util::Program {
const spvc_reflected_resource &res = *res_ptr; const spvc_reflected_resource &res = *res_ptr;
const char *name = res.name; const char *name = res.name;
if (name[0] == '_') continue; if (name[0] == '_') continue;
unsigned spirv_location = spvc_compiler_get_decoration(compiler, res.id, unsigned spirv_location = spvc_compiler_get_decoration(compiler, res.id,
SpvDecorationLocation); SpvDecorationLocation);
GLint final_location; GLint final_location;
if (spirv_location > 0) { spvc_type_id type_id = res.type_id;
if (used_locations.find(spirv_location) != used_locations.end()) { spvc_type type = spvc_compiler_get_type_handle(compiler, type_id);
infoLog += "\nLocation conflict for uniform: " + std::string(name); spvc_basetype base_type = spvc_type_get_basetype(type);
continue; GLenum gl_type = GL_NONE;
if (spirv_location >= 0 && base_type != SPVC_BASETYPE_SAMPLED_IMAGE) {
auto conflict_it = used_locations.find(spirv_location);
if (conflict_it != used_locations.end()) {
// Check if the conflicting uniform is a sampler
std::string conflicting_name;
for (const auto& entry : prog.uniformLocations) {
if (entry.second == spirv_location) {
conflicting_name = entry.first;
break;
}
}
if(conflicting_name == std::string(name)) {
continue;
} else if (!conflicting_name.empty() && prog.uniformValues.count(conflicting_name) &&
MG_GL::GL::IsSamplerType(prog.uniformValues[conflicting_name].type)) {
// Reassign location for the sampler
GLint new_sampler_loc = auto_location++;
while (used_locations.find(new_sampler_loc) != used_locations.end()) new_sampler_loc++;
prog.uniformLocations[conflicting_name] = new_sampler_loc;
used_locations.erase(conflict_it); // Remove old sampler location
used_locations.insert(new_sampler_loc); // Add new sampler location
} else {
infoLog += "\nLocation conflict for uniform: " + std::string(name) + " at location " + std::to_string(spirv_location);
infoLog += "\nExisting uniforms and locations:";
for (const auto& entry : prog.uniformLocations) {
infoLog += "\n " + entry.first + ": " + std::to_string(entry.second);
}
infoLog += "\nUsed locations set:";
for (GLint loc : used_locations) infoLog += " " + std::to_string(loc);
continue;
}
} }
final_location = spirv_location; final_location = spirv_location;
} else { } else {
@@ -184,11 +910,6 @@ namespace MG_Util::Program {
used_locations.insert(final_location); used_locations.insert(final_location);
spvc_type_id type_id = res.type_id;
spvc_type type = spvc_compiler_get_type_handle(compiler, type_id);
spvc_basetype base_type = spvc_type_get_basetype(type);
GLenum gl_type = GL_NONE;
if (base_type == SPVC_BASETYPE_SAMPLED_IMAGE) { if (base_type == SPVC_BASETYPE_SAMPLED_IMAGE) {
SpvDim dim = spvc_type_get_image_dimension(type); SpvDim dim = spvc_type_get_image_dimension(type);
bool is_array = spvc_type_get_image_arrayed(type); bool is_array = spvc_type_get_image_arrayed(type);
@@ -401,7 +1122,7 @@ namespace MG_Util::Program {
spvc_context_destroy(context); spvc_context_destroy(context);
} }
std::string CompileSPIRVToGLSL(std::vector<unsigned int> spirv, uint glslVersion, bool isES) { std::string CompileSPIRVToGLSL(std::vector<unsigned int> spirv, uint glslVersion, bool isES, bool isVkGLSL) {
spvc_context context = nullptr; spvc_context context = nullptr;
spvc_parsed_ir ir = nullptr; spvc_parsed_ir ir = nullptr;
spvc_compiler compiler_glsl = nullptr; spvc_compiler compiler_glsl = nullptr;
@@ -420,12 +1141,15 @@ namespace MG_Util::Program {
spvc_compiler_create_shader_resources(compiler_glsl, &resources); spvc_compiler_create_shader_resources(compiler_glsl, &resources);
spvc_resources_get_resource_list_for_type(resources, SPVC_RESOURCE_TYPE_UNIFORM_BUFFER, &list, &count); spvc_resources_get_resource_list_for_type(resources, SPVC_RESOURCE_TYPE_UNIFORM_BUFFER, &list, &count);
spvc_compiler_create_compiler_options(compiler_glsl, &options); spvc_compiler_create_compiler_options(compiler_glsl, &options);
spvc_compiler_options_set_uint(options, SPVC_COMPILER_OPTION_GLSL_VERSION, glslVersion); spvc_compiler_options_set_uint(options, SPVC_COMPILER_OPTION_GLSL_VERSION, glslVersion);
spvc_compiler_options_set_bool(options, SPVC_COMPILER_OPTION_GLSL_ES, isES ? SPVC_TRUE : SPVC_FALSE); spvc_compiler_options_set_bool(options, SPVC_COMPILER_OPTION_GLSL_ES, isES ? SPVC_TRUE : SPVC_FALSE);
spvc_compiler_options_set_bool(options, SPVC_COMPILER_OPTION_GLSL_VULKAN_SEMANTICS, isVkGLSL ? SPVC_TRUE : SPVC_FALSE);
spvc_compiler_install_compiler_options(compiler_glsl, options); spvc_compiler_install_compiler_options(compiler_glsl, options);
spvc_compiler_compile(compiler_glsl, &result); spvc_compiler_compile(compiler_glsl, &result);
if (!result) { if (!result) {
MG_Util::Debug::LogE("Failed to compile the shader to GLSL: %s", spvc_context_get_last_error_string(context));
return{}; return{};
} }
@@ -435,4 +1159,4 @@ namespace MG_Util::Program {
return essl; return essl;
} }
} }
+14 -5
View File
@@ -5,8 +5,6 @@
#ifndef MOBILEGL_GLSLTOOL_H #ifndef MOBILEGL_GLSLTOOL_H
#define MOBILEGL_GLSLTOOL_H #define MOBILEGL_GLSLTOOL_H
#include "../../Includes.h"
namespace MG_Util::Program { namespace MG_Util::Program {
inline static TBuiltInResource InitResources() inline static TBuiltInResource InitResources()
{ {
@@ -173,11 +171,22 @@ namespace MG_Util::Program {
} }
} }
std::vector<unsigned> CompileGLSLToSPIRV(GLenum shaderType, const std::string& source, std::string& infoLog); std::vector<unsigned> CompileGLSLToSPIRV(GLenum shaderType, const std::string& source,
std::string CompileGLSLToTShader(GLenum shaderType, const std::string& source, glslang::TShader *&shader); std::string& infoLog, bool isVkGLSL = false, GLenum additionalShaderType = 0,
const std::string& additionalShaderSource = {});
std::string CompileGLSLToTShader(GLenum shaderType, const std::string& source,
glslang::TShader *&shader, bool isVkGLSL = false);
std::vector<std::vector<unsigned>> CompileMultipleShadersToSPIRV(const ProgramState& state, ProgramObject& prog, std::string& infoLog); std::vector<std::vector<unsigned>> CompileMultipleShadersToSPIRV(const ProgramState& state, ProgramObject& prog, std::string& infoLog);
void ReflectSPIRVUniforms(const std::vector<std::vector<unsigned>>& allSpirv, ProgramObject& prog, std::string& infoLog); void ReflectSPIRVUniforms(const std::vector<std::vector<unsigned>>& allSpirv, ProgramObject& prog, std::string& infoLog);
std::string CompileSPIRVToGLSL(std::vector<unsigned int> spirv, uint glslVersion, bool isES); std::string CompileSPIRVToGLSL(std::vector<unsigned int> spirv, uint glslVersion, bool isES, bool isVkGLSL = false);
std::pair<std::string, std::string> GenerateDefaultUBOForGLSL(const std::pair<std::string,
std::string>& glslSources);
void GenerateDefaultUBOForGLSL_Multi(
MG_Global::unordered_map<GLuint, std::string> &shaderSources, std::vector<std::string>& outUniformBufferNames);
std::string BindInputLayoutLocationsForGLSL(std::vector<uint32_t>& spirv,
MG_Global::unordered_map<std::string, GLint>&
name_location_map);
void RenameGLSLBuiltinsForVulkan(std::string &src);
} }
#endif //MOBILEGL_GLSLTOOL_H #endif //MOBILEGL_GLSLTOOL_H