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
+13 -3
View File
@@ -56,6 +56,8 @@ add_library(${CMAKE_PROJECT_NAME} SHARED
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()
+41 -26
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));
} }
@@ -142,6 +288,7 @@ namespace MG_GL::GL {
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);
+123 -18
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,32 +243,258 @@ 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) {
MG_Util::Debug::LogD("glFramebufferTexture2D, target: %s, attach: %s, textarget: %s, tex: %u, level: %d", MG_Util::Debug::LogD("glFramebufferTexture2D, target: %s, attach: %s, textarget: %s, tex: %u, level: %d",
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));
} }
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, 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
+71 -54
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:
@@ -326,3 +332,14 @@ GLuint BufferState::GetCurrentBinding(GLenum target) const {
} }
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);
+50 -27
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;
@@ -119,9 +128,7 @@ GLenum ProgramState::FinalizeProgramPipeline(GLuint program) {
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);
+747 -23
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;
@@ -169,10 +863,42 @@ namespace MG_Util::Program {
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{};
} }
+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