From 3bd8a62aa8d2707a02ea8a3a49403793c098edaf Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Fri, 5 Jun 2026 10:41:23 +0800 Subject: [PATCH] [Feat] (MG_Backend/DirectGLES): support compute shaders --- MobileGL/MG_Backend/BackendObject.h | 17 + .../DirectGLES/BackendObject_DirectGLES.cpp | 18 +- MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp | 372 +++++++++++++++++- MobileGL/MG_Backend/DirectGLES/DirectGLES.h | 17 + .../MG_Impl/GLImpl/Drawing/GL_Drawing.cpp | 46 +++ MobileGL/MG_Impl/GLImpl/Drawing/GL_Drawing.h | 4 + .../MG_Impl/GLImpl/Exporting/Definitions.cpp | 28 +- MobileGL/MG_Impl/GLImpl/Getter/GL_Getter.cpp | 92 ++++- MobileGL/MG_Impl/GLImpl/Getter/GL_Getter.h | 2 + .../MG_Impl/GLImpl/Program/GL_Program.cpp | 107 +++++ MobileGL/MG_Impl/GLImpl/Program/GL_Program.h | 9 + .../MG_Impl/GLImpl/Texture/GL_Texture.cpp | 52 +++ MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.h | 2 + MobileGL/MG_State/GLState/Core.cpp | 8 + MobileGL/MG_State/GLState/Core.h | 2 + .../GLState/TextureState/TextureState.cpp | 17 + .../GLState/TextureState/TextureState.h | 24 ++ .../MG_Util/BackendLoaders/OpenGL/Loader.cpp | 1 + .../MG_Util/BackendLoaders/OpenGL/Loader.h | 3 + 19 files changed, 775 insertions(+), 46 deletions(-) diff --git a/MobileGL/MG_Backend/BackendObject.h b/MobileGL/MG_Backend/BackendObject.h index 03904df2..ba8f8ae5 100644 --- a/MobileGL/MG_Backend/BackendObject.h +++ b/MobileGL/MG_Backend/BackendObject.h @@ -64,6 +64,23 @@ namespace MobileGL { void (*ReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels); void (*GetTexImage)(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels); + void (*DispatchCompute)(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ); + void (*DispatchComputeIndirect)(GLintptr indirect); + void (*MemoryBarrier)(GLbitfield barriers); + void (*MemoryBarrierByRegion)(GLbitfield barriers); + void (*BindImageTexture)(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, + GLenum access, GLenum format); + void (*GetIntegeri_v)(GLenum target, GLuint index, GLint* data); + void (*GetInteger64i_v)(GLenum target, GLuint index, GLint64* data); + void (*GetProgramInterfaceiv)(GLuint program, GLenum programInterface, GLenum pname, GLint* params); + GLuint (*GetProgramResourceIndex)(GLuint program, GLenum programInterface, const GLchar* name); + void (*GetProgramResourceName)(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, + GLsizei* length, GLchar* name); + void (*GetProgramResourceiv)(GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, + const GLenum* props, GLsizei bufSize, GLsizei* length, GLint* params); + GLint (*GetProgramResourceLocation)(GLuint program, GLenum programInterface, const GLchar* name); + GLint (*GetProgramResourceLocationIndex)(GLuint program, GLenum programInterface, const GLchar* name); + void (*ShaderStorageBlockBinding)(GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding); }; struct GlobalBackendFunctionsTable { GLFunctionsTable GL; diff --git a/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp index 577e16f2..32a9b692 100644 --- a/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp @@ -119,7 +119,9 @@ namespace MobileGL::MG_Backend::DirectGLES { .TargetGLVersion = {3, 3, 0}, // Target OpenGL Version .TargetGLSLVersion = {4, 6, 0}, // Target Shading Language Version .Extensions = {V_OpenGL30, V_OpenGL31, V_OpenGL32, // OpenGL Extensions - V_OpenGL33, E_GL_ARB_draw_buffers_blend}, + V_OpenGL33, E_GL_ARB_draw_buffers_blend, E_GL_ARB_compute_shader, + E_GL_ARB_shader_storage_buffer_object, E_GL_ARB_shader_image_load_store, + E_GL_ARB_program_interface_query}, .IsCompatibilityProfile = false // Is Compatibility Profile }, .StaticBackendCapability = {.AllowVSOnlyPrograms = false} // Backend Capability @@ -164,6 +166,20 @@ namespace MobileGL::MG_Backend::DirectGLES { funcsTable.GL.DrawArraysInstanced = DrawArraysInstanced; funcsTable.GL.DrawElementsIndirect = DrawElementsIndirect; funcsTable.GL.DrawArraysIndirect = DrawArraysIndirect; + funcsTable.GL.DispatchCompute = DispatchCompute; + funcsTable.GL.DispatchComputeIndirect = DispatchComputeIndirect; + funcsTable.GL.MemoryBarrier = MemoryBarrier; + funcsTable.GL.MemoryBarrierByRegion = MemoryBarrierByRegion; + funcsTable.GL.BindImageTexture = BindImageTexture; + funcsTable.GL.GetIntegeri_v = GetIntegeri_v; + funcsTable.GL.GetInteger64i_v = GetInteger64i_v; + funcsTable.GL.GetProgramInterfaceiv = GetProgramInterfaceiv; + funcsTable.GL.GetProgramResourceIndex = GetProgramResourceIndex; + funcsTable.GL.GetProgramResourceName = GetProgramResourceName; + funcsTable.GL.GetProgramResourceiv = GetProgramResourceiv; + funcsTable.GL.GetProgramResourceLocation = GetProgramResourceLocation; + funcsTable.GL.GetProgramResourceLocationIndex = GetProgramResourceLocationIndex; + funcsTable.GL.ShaderStorageBlockBinding = ShaderStorageBlockBinding; funcsTable.GL.Clear = Clear; funcsTable.GL.ClearBufferfi = ClearBufferfi; funcsTable.GL.ClearBufferfv = ClearBufferfv; diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp index 56a83b03..244b986f 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp @@ -105,6 +105,59 @@ namespace MobileGL::MG_Backend::DirectGLES { backendObj->SyncToBackend(bufferObject); } + void SyncBufferBindingPoints(BufferTarget target, GLenum glTarget) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif + auto bindingPointCnt = MG_State::pGLContext->GetBufferBindingPointCount(target); + for (SizeT i = 0; i < bindingPointCnt; ++i) { + auto& point = MG_State::pGLContext->GetBufferBindingPoint(target, i); + auto& obj = point.GetBoundObject(); + if (!obj) { + g_GLESFuncs.glBindBufferBase(glTarget, static_cast(i), 0); + continue; + } + + CreateAndSyncBufferObject(obj); + const auto& backendBufferIt = g_backendBufferObjects.find(obj.get()); + if (backendBufferIt == g_backendBufferObjects.end()) { + MGLOG_E("No backend buffer found for %s binding point %zu.", + MG_Util::ConvertGLEnumToString(glTarget).c_str(), i); + continue; + } + + const auto& range = point.GetRange(); + auto backendBufferId = backendBufferIt->second->GetBackendBufferId(); + if (range.start == 0 && range.end >= obj->GetSize()) { + g_GLESFuncs.glBindBufferBase(glTarget, static_cast(i), backendBufferId); + } else { + const auto start = std::min(range.start, obj->GetSize()); + const auto end = std::min(range.end, obj->GetSize()); + g_GLESFuncs.glBindBufferRange(glTarget, static_cast(i), backendBufferId, + static_cast(start), static_cast(end - start)); + } + } + } + + void SyncBoundBuffer(BufferTarget target, GLenum glTarget) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif + auto& bufferObject = MG_State::pGLContext->GetBufferBindingSlot(target).GetBoundObject(); + if (!bufferObject) { + g_GLESFuncs.glBindBuffer(glTarget, 0); + return; + } + + CreateAndSyncBufferObject(bufferObject); + const auto& backendBufferIt = g_backendBufferObjects.find(bufferObject.get()); + if (backendBufferIt == g_backendBufferObjects.end()) { + MGLOG_E("No backend buffer found for %s.", MG_Util::ConvertGLEnumToString(glTarget).c_str()); + return; + } + backendBufferIt->second->Bind(glTarget); + } + void SyncNeccessaryBuffers(Bool includeIBO = false, Bool includeIndirectBuffer = false) { #ifdef TRACY_ENABLE ZoneScopedC(TRACY_ZONECOLOR_BACKEND); @@ -112,7 +165,7 @@ namespace MobileGL::MG_Backend::DirectGLES { g_backendBufferObjects.CollectGarbageIfNeeded(); // All buffers we need are: - // 1.VBO 2.IBO (if needed) 3.UBO 4.IndirectBuffer (if needed) 5.SSBO (TODO) + // 1.VBO 2.IBO (if needed) 3.UBO 4.IndirectBuffer (if needed) // PBO is not needed since it should be handled in frontend const auto& currentVAOObject = MG_State::pGLContext->GetBoundVertexArray(); @@ -147,14 +200,18 @@ namespace MobileGL::MG_Backend::DirectGLES { } } - // UBO - auto uboBindingPointCnt = MG_State::pGLContext->GetBufferBindingPointCount(BufferTarget::Uniform); - for (SizeT i = 0; i < uboBindingPointCnt; ++i) { - auto& point = MG_State::pGLContext->GetBufferBindingPoint(BufferTarget::Uniform, i); - auto& obj = point.GetBoundObject(); - if (obj) { - CreateAndSyncBufferObject(obj); - } + SyncBufferBindingPoints(BufferTarget::Uniform, GL_UNIFORM_BUFFER); + } + + void SyncComputeBuffers(Bool includeDispatchIndirectBuffer) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif + g_backendBufferObjects.CollectGarbageIfNeeded(); + SyncBufferBindingPoints(BufferTarget::Uniform, GL_UNIFORM_BUFFER); + SyncBufferBindingPoints(BufferTarget::ShaderStorage, GL_SHADER_STORAGE_BUFFER); + if (includeDispatchIndirectBuffer) { + SyncBoundBuffer(BufferTarget::DispatchIndirect, GL_DISPATCH_INDIRECT_BUFFER); } } } // namespace BufferImpl @@ -234,6 +291,31 @@ namespace MobileGL::MG_Backend::DirectGLES { } } } + + void SyncImageTextureBinding(Uint unit) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif + auto& imageBinding = MG_State::pGLContext->GetImageTextureBinding(static_cast(unit)); + if (!imageBinding.Texture) { + g_GLESFuncs.glBindImageTexture(unit, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8); + return; + } + + auto& backendTexture = SyncTextureObjectToBackend(imageBinding.Texture); + g_GLESFuncs.glBindImageTexture(unit, backendTexture->GetBackendTextureId(), imageBinding.Level, + imageBinding.Layered, imageBinding.Layer, imageBinding.Access, + imageBinding.Format); + } + + void SyncImageTextureBindings() { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif + for (Uint unit = 0; unit < MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS; ++unit) { + SyncImageTextureBinding(unit); + } + } } // namespace TextureImpl namespace FramebufferImpl { @@ -588,6 +670,7 @@ namespace MobileGL::MG_Backend::DirectGLES { if (backendProgramIt != PrgramImpl::g_backendProgramObjects.end()) { backendProgramIt->second->Use(); auto backendProgramId = backendProgramIt->second->GetBackendProgramId(); + // Global UBO if (currentProgram->GetUBOSize() > 0) { #ifdef TRACY_ENABLE @@ -600,11 +683,15 @@ namespace MobileGL::MG_Backend::DirectGLES { Uint blockIndex = g_GLESFuncs.glGetUniformBlockIndex(backendProgramId, MG_Util::ShaderTranspiler::GLOBAL_UBO_NAME); + if (blockIndex == GL_INVALID_INDEX) { + MGLOG_W("Program %u has frontend global UBO storage, but backend has no %s block.", + currentProgram->GetExternalIndex(), MG_Util::ShaderTranspiler::GLOBAL_UBO_NAME); + } else { + g_GLESFuncs.glUniformBlockBinding(backendProgramId, blockIndex, 0); - g_GLESFuncs.glUniformBlockBinding(backendProgramId, blockIndex, 0); - - g_GLESFuncs.glBindBufferBase(GL_UNIFORM_BUFFER, 0, - backendProgramIt->second->GetBackendGlobalUBOId()); + g_GLESFuncs.glBindBufferBase(GL_UNIFORM_BUFFER, 0, + backendProgramIt->second->GetBackendGlobalUBOId()); + } } { @@ -655,10 +742,11 @@ namespace MobileGL::MG_Backend::DirectGLES { #endif // Sampler unit binding auto maxUniformLoc = currentProgram->GetMaxUniformLocation(); - for (int loc = 0; loc < maxUniformLoc; ++loc) { + for (Uint loc = 0; loc <= maxUniformLoc; ++loc) { + auto& name = currentProgram->GetUniformName(loc); + if (name.empty()) continue; auto unit = currentProgram->GetUniformSamplerOrImageUnitIndex(loc); if (unit == -1) continue; - auto& name = currentProgram->GetUniformName(loc); auto locAtBackend = g_GLESFuncs.glGetUniformLocation( backendProgramIt->second->GetBackendProgramId(), name.c_str()); g_GLESFuncs.glUniform1i(locAtBackend, unit); @@ -687,6 +775,55 @@ namespace MobileGL::MG_Backend::DirectGLES { } } + void PrepareForCompute(Bool includeDispatchIndirectBuffer) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif + BufferImpl::SyncComputeBuffers(includeDispatchIndirectBuffer); + TextureImpl::SyncNeccessaryTextures(); + TextureImpl::SyncImageTextureBindings(); + PrgramImpl::SyncCurrentProgram(); + + const auto& currentProgram = MG_State::pGLContext->GetCurrentProgram(); + if (!currentProgram || !currentProgram->GetLinkStatus()) { + g_GLESFuncs.glUseProgram(0); + return; + } + + const auto& backendProgramIt = PrgramImpl::g_backendProgramObjects.find(currentProgram.get()); + if (backendProgramIt != PrgramImpl::g_backendProgramObjects.end()) { + backendProgramIt->second->Use(); + } else { + g_GLESFuncs.glUseProgram(0); + MGLOG_E("No backend program found (maybe not synced) for current compute program."); + } + } + + GLuint GetBackendProgramId(GLuint program) { + if (!MG_State::pGLContext->ValidateProgramName(program)) { + MGLOG_E("Invalid frontend program object: %u", program); + return 0; + } + + auto& programObject = MG_State::pGLContext->GetProgramObject(program); + if (!programObject) { + MGLOG_E("Program object %u is null.", program); + return 0; + } + + const auto& backendProgramIt = PrgramImpl::g_backendProgramObjects.find(programObject.get()); + Bool exist = (backendProgramIt != PrgramImpl::g_backendProgramObjects.end()); + auto& backendObj = + exist ? backendProgramIt->second : PrgramImpl::g_backendProgramObjects.GetOrCreate(programObject); + if (!exist) { + backendObj = MakeShared(); + } + if (!backendObj->GetBackendProgramId()) { + backendObj->SyncToBackend(programObject); + } + return backendObj->GetBackendProgramId(); + } + void Clear(GLbitfield mask) { #if MOBILEGL_LOG_ACTIVE_LEVEL <= MOBILEGL_LOG_LEVEL_DEBUG && MOBILEGL_ENABLE_SCOPE_MARKER DebugImpl::OpenGLScopeMarker marker(__func__); @@ -1132,6 +1269,211 @@ namespace MobileGL::MG_Backend::DirectGLES { return g_GLESFuncs.glGetString(name); } + void DispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ) { +#if MOBILEGL_LOG_ACTIVE_LEVEL <= MOBILEGL_LOG_LEVEL_DEBUG && MOBILEGL_ENABLE_SCOPE_MARKER + DebugImpl::OpenGLScopeMarker marker(__func__); +#endif + PrepareForCompute(false); + g_GLESFuncs.glDispatchCompute(numGroupsX, numGroupsY, numGroupsZ); + } + + void DispatchComputeIndirect(GLintptr indirect) { +#if MOBILEGL_LOG_ACTIVE_LEVEL <= MOBILEGL_LOG_LEVEL_DEBUG && MOBILEGL_ENABLE_SCOPE_MARKER + DebugImpl::OpenGLScopeMarker marker(__func__); +#endif + PrepareForCompute(true); + g_GLESFuncs.glDispatchComputeIndirect(indirect); + } + + void MemoryBarrier(GLbitfield barriers) { + g_GLESFuncs.glMemoryBarrier(barriers); + } + + void MemoryBarrierByRegion(GLbitfield barriers) { + g_GLESFuncs.glMemoryBarrierByRegion(barriers); + } + + void BindImageTexture(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, + GLenum format) { + (void)texture; + (void)level; + (void)layered; + (void)layer; + (void)access; + (void)format; + TextureImpl::SyncImageTextureBinding(unit); + } + + void GetIntegeri_v(GLenum target, GLuint index, GLint* data) { + if (!data) return; + + switch (target) { + case GL_SHADER_STORAGE_BUFFER_BINDING: { + auto& point = MG_State::pGLContext->GetBufferBindingPoint(BufferTarget::ShaderStorage, index); + auto& obj = point.GetBoundObject(); + *data = obj ? static_cast(obj->GetExternalIndex()) : 0; + return; + } + case GL_SHADER_STORAGE_BUFFER_START: { + auto& point = MG_State::pGLContext->GetBufferBindingPoint(BufferTarget::ShaderStorage, index); + *data = static_cast(point.GetRange().start); + return; + } + case GL_SHADER_STORAGE_BUFFER_SIZE: { + auto& point = MG_State::pGLContext->GetBufferBindingPoint(BufferTarget::ShaderStorage, index); + auto& obj = point.GetBoundObject(); + if (!obj) { + *data = 0; + return; + } + const auto& range = point.GetRange(); + const auto start = std::min(range.start, obj->GetSize()); + const auto end = std::min(range.end, obj->GetSize()); + *data = static_cast(end - start); + return; + } + case GL_IMAGE_BINDING_NAME: { + if (index >= MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS) { + *data = 0; + return; + } + auto& imageBinding = MG_State::pGLContext->GetImageTextureBinding(static_cast(index)); + *data = imageBinding.Texture ? static_cast(imageBinding.Texture->GetExternalIndex()) : 0; + return; + } + case GL_IMAGE_BINDING_LEVEL: { + if (index >= MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS) { + *data = 0; + return; + } + auto& imageBinding = MG_State::pGLContext->GetImageTextureBinding(static_cast(index)); + *data = imageBinding.Level; + return; + } + case GL_IMAGE_BINDING_LAYERED: { + if (index >= MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS) { + *data = 0; + return; + } + auto& imageBinding = MG_State::pGLContext->GetImageTextureBinding(static_cast(index)); + *data = imageBinding.Layered; + return; + } + case GL_IMAGE_BINDING_LAYER: { + if (index >= MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS) { + *data = 0; + return; + } + auto& imageBinding = MG_State::pGLContext->GetImageTextureBinding(static_cast(index)); + *data = imageBinding.Layer; + return; + } + case GL_IMAGE_BINDING_ACCESS: { + if (index >= MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS) { + *data = 0; + return; + } + auto& imageBinding = MG_State::pGLContext->GetImageTextureBinding(static_cast(index)); + *data = static_cast(imageBinding.Access); + return; + } + case GL_IMAGE_BINDING_FORMAT: { + if (index >= MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS) { + *data = 0; + return; + } + auto& imageBinding = MG_State::pGLContext->GetImageTextureBinding(static_cast(index)); + *data = static_cast(imageBinding.Format); + return; + } + default: + if (g_GLESFuncs.glGetIntegeri_v) { + g_GLESFuncs.glGetIntegeri_v(target, index, data); + } else { + *data = 0; + } + return; + } + } + + void GetInteger64i_v(GLenum target, GLuint index, GLint64* data) { + if (!data) return; + + switch (target) { + case GL_SHADER_STORAGE_BUFFER_START: { + auto& point = MG_State::pGLContext->GetBufferBindingPoint(BufferTarget::ShaderStorage, index); + *data = static_cast(point.GetRange().start); + return; + } + case GL_SHADER_STORAGE_BUFFER_SIZE: { + auto& point = MG_State::pGLContext->GetBufferBindingPoint(BufferTarget::ShaderStorage, index); + auto& obj = point.GetBoundObject(); + if (!obj) { + *data = 0; + return; + } + const auto& range = point.GetRange(); + const auto start = std::min(range.start, obj->GetSize()); + const auto end = std::min(range.end, obj->GetSize()); + *data = static_cast(end - start); + return; + } + default: + if (g_GLESFuncs.glGetInteger64i_v) { + g_GLESFuncs.glGetInteger64i_v(target, index, data); + } else { + *data = 0; + } + return; + } + } + + void GetProgramInterfaceiv(GLuint program, GLenum programInterface, GLenum pname, GLint* params) { + GLuint backendProgramId = GetBackendProgramId(program); + if (!backendProgramId) return; + g_GLESFuncs.glGetProgramInterfaceiv(backendProgramId, programInterface, pname, params); + } + + GLuint GetProgramResourceIndex(GLuint program, GLenum programInterface, const GLchar* name) { + GLuint backendProgramId = GetBackendProgramId(program); + if (!backendProgramId) return GL_INVALID_INDEX; + return g_GLESFuncs.glGetProgramResourceIndex(backendProgramId, programInterface, name); + } + + void GetProgramResourceName(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, + GLsizei* length, GLchar* name) { + GLuint backendProgramId = GetBackendProgramId(program); + if (!backendProgramId) return; + g_GLESFuncs.glGetProgramResourceName(backendProgramId, programInterface, index, bufSize, length, name); + } + + void GetProgramResourceiv(GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, + const GLenum* props, GLsizei bufSize, GLsizei* length, GLint* params) { + GLuint backendProgramId = GetBackendProgramId(program); + if (!backendProgramId) return; + g_GLESFuncs.glGetProgramResourceiv(backendProgramId, programInterface, index, propCount, props, bufSize, + length, params); + } + + GLint GetProgramResourceLocation(GLuint program, GLenum programInterface, const GLchar* name) { + GLuint backendProgramId = GetBackendProgramId(program); + if (!backendProgramId) return -1; + return g_GLESFuncs.glGetProgramResourceLocation(backendProgramId, programInterface, name); + } + + GLint GetProgramResourceLocationIndex(GLuint program, GLenum programInterface, const GLchar* name) { + (void)program; + (void)programInterface; + (void)name; + return -1; + } + + void ShaderStorageBlockBinding(GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding) { + GLuint backendProgramId = GetBackendProgramId(program); + if (!backendProgramId) return; + g_GLESFuncs.glShaderStorageBlockBinding(backendProgramId, storageBlockIndex, storageBlockBinding); + } + void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) { TextureImpl::SyncNeccessaryTextures(); FramebufferImpl::SyncCurrentFBO(); diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.h b/MobileGL/MG_Backend/DirectGLES/DirectGLES.h index 4b907fa1..4d2dddf4 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.h +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.h @@ -56,6 +56,23 @@ namespace MobileGL::MG_Backend::DirectGLES { const GLubyte* GetString(GLenum name); void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels); void GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels); + void DispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ); + void DispatchComputeIndirect(GLintptr indirect); + void MemoryBarrier(GLbitfield barriers); + void MemoryBarrierByRegion(GLbitfield barriers); + void BindImageTexture(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, + GLenum format); + void GetIntegeri_v(GLenum target, GLuint index, GLint* data); + void GetInteger64i_v(GLenum target, GLuint index, GLint64* data); + void GetProgramInterfaceiv(GLuint program, GLenum programInterface, GLenum pname, GLint* params); + GLuint GetProgramResourceIndex(GLuint program, GLenum programInterface, const GLchar* name); + void GetProgramResourceName(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, + GLsizei* length, GLchar* name); + void GetProgramResourceiv(GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, + const GLenum* props, GLsizei bufSize, GLsizei* length, GLint* params); + GLint GetProgramResourceLocation(GLuint program, GLenum programInterface, const GLchar* name); + GLint GetProgramResourceLocationIndex(GLuint program, GLenum programInterface, const GLchar* name); + void ShaderStorageBlockBinding(GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding); Bool InitWindowSurface(NativeWindowType window); void Present(); void SetEGLFuncsTable(const MG_External::EGLFunctionsTable& eglFuncs); diff --git a/MobileGL/MG_Impl/GLImpl/Drawing/GL_Drawing.cpp b/MobileGL/MG_Impl/GLImpl/Drawing/GL_Drawing.cpp index 70ebd6c0..155a8e03 100644 --- a/MobileGL/MG_Impl/GLImpl/Drawing/GL_Drawing.cpp +++ b/MobileGL/MG_Impl/GLImpl/Drawing/GL_Drawing.cpp @@ -156,6 +156,52 @@ namespace MobileGL::MG_Impl::GLImpl { } /* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */ + void DispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ) { + auto dispatchCompute = MG_Backend::gBackendFunctionsTable.GL.DispatchCompute; + if (!dispatchCompute) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, "Backend does not support compute dispatch.")); + return; + } + dispatchCompute(numGroupsX, numGroupsY, numGroupsZ); + } + + void DispatchComputeIndirect(GLintptr indirect) { + auto dispatchComputeIndirect = MG_Backend::gBackendFunctionsTable.GL.DispatchComputeIndirect; + if (!dispatchComputeIndirect) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, + "Backend does not support indirect compute dispatch.")); + return; + } + dispatchComputeIndirect(indirect); + } + + void MemoryBarrier(GLbitfield barriers) { + auto memoryBarrier = MG_Backend::gBackendFunctionsTable.GL.MemoryBarrier; + if (!memoryBarrier) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, "Backend does not support memory barriers.")); + return; + } + memoryBarrier(barriers); + } + + void MemoryBarrierByRegion(GLbitfield barriers) { + auto memoryBarrierByRegion = MG_Backend::gBackendFunctionsTable.GL.MemoryBarrierByRegion; + if (!memoryBarrierByRegion) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, + "Backend does not support regional memory barriers.")); + return; + } + memoryBarrierByRegion(barriers); + } + void MultiDrawElementsIndirect(GLenum mode, GLenum type, const void* indirect, GLsizei drawcount, GLsizei stride) { MultiDrawElementsIndirect_Backend(mode, type, indirect, drawcount, stride); } diff --git a/MobileGL/MG_Impl/GLImpl/Drawing/GL_Drawing.h b/MobileGL/MG_Impl/GLImpl/Drawing/GL_Drawing.h index b49702d7..64aa08bc 100644 --- a/MobileGL/MG_Impl/GLImpl/Drawing/GL_Drawing.h +++ b/MobileGL/MG_Impl/GLImpl/Drawing/GL_Drawing.h @@ -11,6 +11,10 @@ namespace MobileGL::MG_Impl::GLImpl { /* @INSERTION_POINT:FUNCTION_DECLARATION@ */ + void DispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ); + void DispatchComputeIndirect(GLintptr indirect); + void MemoryBarrier(GLbitfield barriers); + void MemoryBarrierByRegion(GLbitfield barriers); void MultiDrawElementsIndirect(GLenum mode, GLenum type, const void* indirect, GLsizei drawcount, GLsizei stride); void MultiDrawArraysIndirect(GLenum mode, const void* indirect, GLsizei drawcount, GLsizei stride); void DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, diff --git a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp index a692f6e6..1b0e68d5 100644 --- a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp +++ b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp @@ -233,7 +233,7 @@ DECLARE_GL_FUNCTION_HEAD(void, BindVertexArray, GLuint array) DECLARE_GL_FUNCTIO DECLARE_GL_FUNCTION_HEAD(void, DeleteVertexArrays, GLsizei n, const GLuint* arrays) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DeleteVertexArrays, n, arrays) DECLARE_GL_FUNCTION_HEAD(void, GenVertexArrays, GLsizei n, GLuint* arrays) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GenVertexArrays, n, arrays) DECLARE_GL_FUNCTION_HEAD(GLboolean, IsVertexArray, GLuint array) DECLARE_GL_FUNCTION_END(GLboolean, IsVertexArray, array) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetIntegeri_v, GLenum target, GLuint index, GLint* data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetIntegeri_v, target, index, data) +DECLARE_GL_FUNCTION_HEAD(void, GetIntegeri_v, GLenum target, GLuint index, GLint* data) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetIntegeri_v, target, index, data) DECLARE_GL_FUNCTION_STUB_HEAD(void, BeginTransformFeedback, GLenum primitiveMode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BeginTransformFeedback, primitiveMode) DECLARE_GL_FUNCTION_STUB_HEAD(void, EndTransformFeedback) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, EndTransformFeedback) DECLARE_GL_FUNCTION_HEAD(void, BindBufferRange, GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BindBufferRange, target, index, buffer, offset, size) @@ -277,7 +277,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(GLenum, ClientWaitSync, GLsync sync, GLbitfield fl DECLARE_GL_FUNCTION_STUB_HEAD(void, WaitSync, GLsync sync, GLbitfield flags, GLuint64 timeout) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, WaitSync, sync, flags, timeout) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetInteger64v, GLenum pname, GLint64* data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetInteger64v, pname, data) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetSynciv, GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetSynciv, sync, pname, bufSize, length, values) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetInteger64i_v, GLenum target, GLuint index, GLint64* data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetInteger64i_v, target, index, data) +DECLARE_GL_FUNCTION_HEAD(void, GetInteger64i_v, GLenum target, GLuint index, GLint64* data) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetInteger64i_v, target, index, data) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetBufferParameteri64v, GLenum target, GLenum pname, GLint64* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetBufferParameteri64v, target, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GenSamplers, GLsizei count, GLuint* samplers) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GenSamplers, count, samplers) DECLARE_GL_FUNCTION_HEAD(void, DeleteSamplers, GLsizei count, const GLuint* samplers) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DeleteSamplers, count, samplers) @@ -304,17 +304,17 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, InvalidateSubFramebuffer, GLenum target, GLs DECLARE_GL_FUNCTION_STUB_HEAD(void, TexStorage2D, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexStorage2D, target, levels, internalformat, width, height) DECLARE_GL_FUNCTION_STUB_HEAD(void, TexStorage3D, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexStorage3D, target, levels, internalformat, width, height, depth) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetInternalformativ, GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetInternalformativ, target, internalformat, pname, bufSize, params) -DECLARE_GL_FUNCTION_STUB_HEAD(void, DispatchCompute, GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DispatchCompute, num_groups_x, num_groups_y, num_groups_z) -DECLARE_GL_FUNCTION_STUB_HEAD(void, DispatchComputeIndirect, GLintptr indirect) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DispatchComputeIndirect, indirect) +DECLARE_GL_FUNCTION_HEAD(void, DispatchCompute, GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DispatchCompute, num_groups_x, num_groups_y, num_groups_z) +DECLARE_GL_FUNCTION_HEAD(void, DispatchComputeIndirect, GLintptr indirect) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DispatchComputeIndirect, indirect) DECLARE_GL_FUNCTION_HEAD(void, DrawArraysIndirect, GLenum mode, const void* indirect) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DrawArraysIndirect, mode, indirect) DECLARE_GL_FUNCTION_HEAD(void, DrawElementsIndirect, GLenum mode, GLenum type, const void* indirect) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DrawElementsIndirect, mode, type, indirect) DECLARE_GL_FUNCTION_STUB_HEAD(void, FramebufferParameteri, GLenum target, GLenum pname, GLint param) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, FramebufferParameteri, target, pname, param) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetFramebufferParameteriv, GLenum target, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetFramebufferParameteriv, target, pname, params) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetProgramInterfaceiv, GLuint program, GLenum programInterface, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetProgramInterfaceiv, program, programInterface, pname, params) -DECLARE_GL_FUNCTION_STUB_HEAD(GLuint, GetProgramResourceIndex, GLuint program, GLenum programInterface, const GLchar* name) DECLARE_GL_FUNCTION_STUB_END(GLuint, GetProgramResourceIndex, program, programInterface, name) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetProgramResourceName, GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei* length, GLchar* name) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetProgramResourceName, program, programInterface, index, bufSize, length, name) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetProgramResourceiv, GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum* props, GLsizei bufSize, GLsizei* length, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetProgramResourceiv, program, programInterface, index, propCount, props, bufSize, length, params) -DECLARE_GL_FUNCTION_STUB_HEAD(GLint, GetProgramResourceLocation, GLuint program, GLenum programInterface, const GLchar* name) DECLARE_GL_FUNCTION_STUB_END(GLint, GetProgramResourceLocation, program, programInterface, name) +DECLARE_GL_FUNCTION_HEAD(void, GetProgramInterfaceiv, GLuint program, GLenum programInterface, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetProgramInterfaceiv, program, programInterface, pname, params) +DECLARE_GL_FUNCTION_HEAD(GLuint, GetProgramResourceIndex, GLuint program, GLenum programInterface, const GLchar* name) DECLARE_GL_FUNCTION_END(GLuint, GetProgramResourceIndex, program, programInterface, name) +DECLARE_GL_FUNCTION_HEAD(void, GetProgramResourceName, GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei* length, GLchar* name) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetProgramResourceName, program, programInterface, index, bufSize, length, name) +DECLARE_GL_FUNCTION_HEAD(void, GetProgramResourceiv, GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum* props, GLsizei bufSize, GLsizei* length, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetProgramResourceiv, program, programInterface, index, propCount, props, bufSize, length, params) +DECLARE_GL_FUNCTION_HEAD(GLint, GetProgramResourceLocation, GLuint program, GLenum programInterface, const GLchar* name) DECLARE_GL_FUNCTION_END(GLint, GetProgramResourceLocation, program, programInterface, name) DECLARE_GL_FUNCTION_STUB_HEAD(void, UseProgramStages, GLuint pipeline, GLbitfield stages, GLuint program) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UseProgramStages, pipeline, stages, program) DECLARE_GL_FUNCTION_STUB_HEAD(void, ActiveShaderProgram, GLuint pipeline, GLuint program) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ActiveShaderProgram, pipeline, program) DECLARE_GL_FUNCTION_STUB_HEAD(GLuint, CreateShaderProgramv, GLenum type, GLsizei count, const GLchar* const* strings) DECLARE_GL_FUNCTION_STUB_END(GLuint, CreateShaderProgramv, type, count, strings) @@ -358,10 +358,10 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniformMatrix3x4fv, GLuint program, G DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniformMatrix4x3fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniformMatrix4x3fv, program, location, count, transpose, value) DECLARE_GL_FUNCTION_STUB_HEAD(void, ValidateProgramPipeline, GLuint pipeline) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ValidateProgramPipeline, pipeline) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetProgramPipelineInfoLog, GLuint pipeline, GLsizei bufSize, GLsizei* length, GLchar* infoLog) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetProgramPipelineInfoLog, pipeline, bufSize, length, infoLog) -DECLARE_GL_FUNCTION_STUB_HEAD(void, BindImageTexture, GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BindImageTexture, unit, texture, level, layered, layer, access, format) +DECLARE_GL_FUNCTION_HEAD(void, BindImageTexture, GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BindImageTexture, unit, texture, level, layered, layer, access, format) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetBooleani_v, GLenum target, GLuint index, GLboolean* data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetBooleani_v, target, index, data) -DECLARE_GL_FUNCTION_STUB_HEAD(void, MemoryBarrier, GLbitfield barriers) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, MemoryBarrier, barriers) -DECLARE_GL_FUNCTION_STUB_HEAD(void, MemoryBarrierByRegion, GLbitfield barriers) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, MemoryBarrierByRegion, barriers) +DECLARE_GL_FUNCTION_HEAD(void, MemoryBarrier, GLbitfield barriers) DECLARE_GL_FUNCTION_END_NO_RETURN(void, MemoryBarrier, barriers) +DECLARE_GL_FUNCTION_HEAD(void, MemoryBarrierByRegion, GLbitfield barriers) DECLARE_GL_FUNCTION_END_NO_RETURN(void, MemoryBarrierByRegion, barriers) DECLARE_GL_FUNCTION_STUB_HEAD(void, TexStorage2DMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexStorage2DMultisample, target, samples, internalformat, width, height, fixedsamplelocations) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetMultisamplefv, GLenum pname, GLuint index, GLfloat* val) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetMultisamplefv, pname, index, val) DECLARE_GL_FUNCTION_HEAD(void, SampleMaski, GLuint maskNumber, GLbitfield mask) DECLARE_GL_FUNCTION_END_NO_RETURN(void, SampleMaski, maskNumber, mask) @@ -977,8 +977,8 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, InvalidateBufferSubData, GLuint buffer, GLin DECLARE_GL_FUNCTION_STUB_HEAD(void, InvalidateBufferData, GLuint buffer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, InvalidateBufferData, buffer) DECLARE_GL_FUNCTION_HEAD(void, MultiDrawArraysIndirect, GLenum mode, const void* indirect, GLsizei drawcount, GLsizei stride) DECLARE_GL_FUNCTION_END_NO_RETURN(void, MultiDrawArraysIndirect, mode, indirect, drawcount, stride) DECLARE_GL_FUNCTION_HEAD(void, MultiDrawElementsIndirect, GLenum mode, GLenum type, const void* indirect, GLsizei drawcount, GLsizei stride) DECLARE_GL_FUNCTION_END_NO_RETURN(void, MultiDrawElementsIndirect, mode, type, indirect, drawcount, stride) -DECLARE_GL_FUNCTION_STUB_HEAD(GLint, GetProgramResourceLocationIndex, GLuint program, GLenum programInterface, const GLchar* name) DECLARE_GL_FUNCTION_STUB_END(GLint, GetProgramResourceLocationIndex, program, programInterface, name) -DECLARE_GL_FUNCTION_STUB_HEAD(void, ShaderStorageBlockBinding, GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ShaderStorageBlockBinding, program, storageBlockIndex, storageBlockBinding) +DECLARE_GL_FUNCTION_HEAD(GLint, GetProgramResourceLocationIndex, GLuint program, GLenum programInterface, const GLchar* name) DECLARE_GL_FUNCTION_END(GLint, GetProgramResourceLocationIndex, program, programInterface, name) +DECLARE_GL_FUNCTION_HEAD(void, ShaderStorageBlockBinding, GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ShaderStorageBlockBinding, program, storageBlockIndex, storageBlockBinding) DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureView, GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureView, texture, target, origtexture, internalformat, minlevel, numlevels, minlayer, numlayers) DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribLFormat, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribLFormat, attribindex, size, type, relativeoffset) DECLARE_GL_FUNCTION_STUB_HEAD(void, BufferStorage, GLenum target, GLsizeiptr size, const void* data, GLbitfield flags) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BufferStorage, target, size, data, flags) diff --git a/MobileGL/MG_Impl/GLImpl/Getter/GL_Getter.cpp b/MobileGL/MG_Impl/GLImpl/Getter/GL_Getter.cpp index d131ad44..6b5c45ce 100644 --- a/MobileGL/MG_Impl/GLImpl/Getter/GL_Getter.cpp +++ b/MobileGL/MG_Impl/GLImpl/Getter/GL_Getter.cpp @@ -120,6 +120,42 @@ namespace MobileGL::MG_Impl::GLImpl { return (const GLubyte*)extStrings[index].c_str(); } + void GetIntegeri_v(GLenum target, GLuint index, GLint* data) { + if (!data) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", __func__, "data pointer cannot be null")); + return; + } + auto getIntegeri = MG_Backend::gBackendFunctionsTable.GL.GetIntegeri_v; + if (!getIntegeri) { + *data = 0; + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, "Backend does not support indexed integer queries.")); + return; + } + getIntegeri(target, index, data); + } + + void GetInteger64i_v(GLenum target, GLuint index, GLint64* data) { + if (!data) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", __func__, "data pointer cannot be null")); + return; + } + auto getInteger64i = MG_Backend::gBackendFunctionsTable.GL.GetInteger64i_v; + if (!getInteger64i) { + *data = 0; + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, "Backend does not support indexed integer queries.")); + return; + } + getInteger64i(target, index, data); + } + void GetIntegerv(GLenum pname, GLint* params) { MGLOG_D("glGetIntegerv, pname: %s", MG_Util::ConvertGLEnumToString(pname).c_str()); if (!params) { @@ -213,41 +249,47 @@ namespace MobileGL::MG_Impl::GLImpl { *params = 0; // TODO break; case GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS: - *params = 0; // TODO + *params = 16; // TODO: use backend value break; case GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS: - *params = 0; // TODO + *params = 96; // TODO: use backend value break; case GL_MAX_COMPUTE_UNIFORM_BLOCKS: - *params = 0; // TODO + *params = 14; // TODO: use backend value break; case GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS: - *params = 0; // TODO + *params = MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS; // TODO: use backend value break; case GL_MAX_COMPUTE_UNIFORM_COMPONENTS: - *params = 0; // TODO + *params = 1024 * 4; // TODO: use backend value break; case GL_MAX_COMPUTE_ATOMIC_COUNTERS: - *params = 0; // TODO + *params = 8; // TODO: use backend value break; case GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS: - *params = 0; // TODO + *params = 8; // TODO: use backend value break; case GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS: - *params = 0; // TODO + *params = 1024 * 228; // TODO: use backend value break; case GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS: - *params = 0; // TODO + *params = 1024; // TODO: use backend value break; case GL_MAX_COMPUTE_WORK_GROUP_COUNT: - *params = 0; // TODO + GetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, ¶ms[0]); + GetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1, ¶ms[1]); + GetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 2, ¶ms[2]); break; case GL_MAX_COMPUTE_WORK_GROUP_SIZE: - *params = 0; // TODO + GetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0, ¶ms[0]); + GetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 1, ¶ms[1]); + GetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 2, ¶ms[2]); break; - case GL_DISPATCH_INDIRECT_BUFFER_BINDING: - *params = 0; // TODO + case GL_DISPATCH_INDIRECT_BUFFER_BINDING: { + auto& obj = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::DispatchIndirect).GetBoundObject(); + *params = obj ? static_cast(obj->GetExternalIndex()) : 0; break; + } case GL_MAX_DEBUG_GROUP_STACK_DEPTH: *params = 0; // TODO break; @@ -437,6 +479,22 @@ namespace MobileGL::MG_Impl::GLImpl { case GL_MAX_GEOMETRY_UNIFORM_COMPONENTS: *params = 1024 * 4; // TODO break; + case GL_MAX_IMAGE_UNITS: + *params = MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS; // TODO: use backend value + break; + case GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS: + *params = MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS + + MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS; + break; + case GL_MAX_COMBINED_IMAGE_UNIFORMS: + *params = MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS; // TODO: use backend value + break; + case GL_MAX_IMAGE_SAMPLES: + *params = 0; // multisampled image load/store is not exposed by the DirectGLES frontend + break; + case GL_MAX_COMPUTE_IMAGE_UNIFORMS: + *params = MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS; // TODO: use backend value + break; case GL_MAX_INTEGER_SAMPLES: *params = 16; // TODO break; @@ -674,11 +732,13 @@ namespace MobileGL::MG_Impl::GLImpl { case GL_SHADER_COMPILER: *params = 0; // TODO break; - case GL_SHADER_STORAGE_BUFFER_BINDING: - *params = 0; // TODO + case GL_SHADER_STORAGE_BUFFER_BINDING: { + auto& obj = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::ShaderStorage).GetBoundObject(); + *params = obj ? static_cast(obj->GetExternalIndex()) : 0; break; + } case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT: - *params = 0; // TODO + *params = 256; // TODO: use backend value break; case GL_SHADER_STORAGE_BUFFER_START: *params = 0; // TODO diff --git a/MobileGL/MG_Impl/GLImpl/Getter/GL_Getter.h b/MobileGL/MG_Impl/GLImpl/Getter/GL_Getter.h index d7fba7e4..4e5b8d97 100644 --- a/MobileGL/MG_Impl/GLImpl/Getter/GL_Getter.h +++ b/MobileGL/MG_Impl/GLImpl/Getter/GL_Getter.h @@ -14,5 +14,7 @@ namespace MobileGL::MG_Impl::GLImpl { const GLubyte* GetString(GLenum name); const GLubyte* GetStringi(GLenum name, GLuint index); void GetIntegerv(GLenum pname, GLint* params); + void GetIntegeri_v(GLenum target, GLuint index, GLint* data); + void GetInteger64i_v(GLenum target, GLuint index, GLint64* data); GLenum GetError(); } // namespace MobileGL::MG_Impl::GLImpl diff --git a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp index 1fdfa756..6ed32999 100644 --- a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp +++ b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp @@ -13,6 +13,7 @@ #include #include #include +#include namespace MobileGL::MG_Impl::GLImpl { static bool CheckShaderNameValidity(Uint shader) { @@ -1168,6 +1169,112 @@ namespace MobileGL::MG_Impl::GLImpl { return GetFragDataLocation_State(program, name); } + void GetProgramInterfaceiv(GLuint program, GLenum programInterface, GLenum pname, GLint* params) { + auto& programObject = TryToGetProgramObject(program); + if (!programObject || !programObject->GetLinkStatus()) return; + auto getProgramInterfaceiv = MG_Backend::gBackendFunctionsTable.GL.GetProgramInterfaceiv; + if (!getProgramInterfaceiv) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, + "Backend does not support program interface queries.")); + return; + } + getProgramInterfaceiv(program, programInterface, pname, params); + } + + GLuint GetProgramResourceIndex(GLuint program, GLenum programInterface, const GLchar* name) { + auto& programObject = TryToGetProgramObject(program); + if (!programObject || !programObject->GetLinkStatus()) return GL_INVALID_INDEX; + auto getProgramResourceIndex = MG_Backend::gBackendFunctionsTable.GL.GetProgramResourceIndex; + if (!getProgramResourceIndex) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, + "Backend does not support program interface queries.")); + return GL_INVALID_INDEX; + } + return getProgramResourceIndex(program, programInterface, name); + } + + void GetProgramResourceName(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, + GLsizei* length, GLchar* name) { + auto& programObject = TryToGetProgramObject(program); + if (!programObject || !programObject->GetLinkStatus()) return; + if (bufSize < 0) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", __func__, "bufSize must be non-negative.")); + return; + } + auto getProgramResourceName = MG_Backend::gBackendFunctionsTable.GL.GetProgramResourceName; + if (!getProgramResourceName) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, + "Backend does not support program interface queries.")); + return; + } + getProgramResourceName(program, programInterface, index, bufSize, length, name); + } + + void GetProgramResourceiv(GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, + const GLenum* props, GLsizei bufSize, GLsizei* length, GLint* params) { + auto& programObject = TryToGetProgramObject(program); + if (!programObject || !programObject->GetLinkStatus()) return; + if (propCount < 0 || bufSize < 0) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", __func__, "propCount and bufSize must be non-negative.")); + return; + } + auto getProgramResourceiv = MG_Backend::gBackendFunctionsTable.GL.GetProgramResourceiv; + if (!getProgramResourceiv) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, + "Backend does not support program interface queries.")); + return; + } + getProgramResourceiv(program, programInterface, index, propCount, props, bufSize, length, params); + } + + GLint GetProgramResourceLocation(GLuint program, GLenum programInterface, const GLchar* name) { + auto& programObject = TryToGetProgramObject(program); + if (!programObject || !programObject->GetLinkStatus()) return -1; + auto getProgramResourceLocation = MG_Backend::gBackendFunctionsTable.GL.GetProgramResourceLocation; + if (!getProgramResourceLocation) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, + "Backend does not support program interface queries.")); + return -1; + } + return getProgramResourceLocation(program, programInterface, name); + } + + GLint GetProgramResourceLocationIndex(GLuint program, GLenum programInterface, const GLchar* name) { + auto& programObject = TryToGetProgramObject(program); + if (!programObject || !programObject->GetLinkStatus()) return -1; + auto getProgramResourceLocationIndex = MG_Backend::gBackendFunctionsTable.GL.GetProgramResourceLocationIndex; + if (!getProgramResourceLocationIndex) return -1; + return getProgramResourceLocationIndex(program, programInterface, name); + } + + void ShaderStorageBlockBinding(GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding) { + auto& programObject = TryToGetProgramObject(program); + if (!programObject || !programObject->GetLinkStatus()) return; + auto shaderStorageBlockBinding = MG_Backend::gBackendFunctionsTable.GL.ShaderStorageBlockBinding; + if (!shaderStorageBlockBinding) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, + "Backend does not support shader storage block binding.")); + return; + } + shaderStorageBlockBinding(program, storageBlockIndex, storageBlockBinding); + } + void ValidateProgram(GLuint program) { ValidateProgram_State(program); } diff --git a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.h b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.h index 53f56a90..dd3db51c 100644 --- a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.h +++ b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.h @@ -63,5 +63,14 @@ namespace MobileGL::MG_Impl::GLImpl { GLchar* uniformBlockName); void BindFragDataLocation(GLuint program, GLuint colorNumber, const char* name); GLint GetFragDataLocation(GLuint program, const char* name); + void GetProgramInterfaceiv(GLuint program, GLenum programInterface, GLenum pname, GLint* params); + GLuint GetProgramResourceIndex(GLuint program, GLenum programInterface, const GLchar* name); + void GetProgramResourceName(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, + GLsizei* length, GLchar* name); + void GetProgramResourceiv(GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, + const GLenum* props, GLsizei bufSize, GLsizei* length, GLint* params); + GLint GetProgramResourceLocation(GLuint program, GLenum programInterface, const GLchar* name); + GLint GetProgramResourceLocationIndex(GLuint program, GLenum programInterface, const GLchar* name); + void ShaderStorageBlockBinding(GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding); void ValidateProgram(GLuint program); } // namespace MobileGL::MG_Impl::GLImpl diff --git a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp index b636b784..4293d50a 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp +++ b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp @@ -1471,6 +1471,58 @@ namespace MobileGL::MG_Impl::GLImpl { } /* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */ + void BindImageTexture(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, + GLenum format) { + if (unit >= MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", __func__, "Image texture unit is out of range.")); + return; + } + if (level < 0) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", __func__, "Texture level must be non-negative.")); + return; + } + if (layer < 0 && layered == GL_FALSE) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", __func__, "Texture layer must be non-negative.")); + return; + } + if (access != GL_READ_ONLY && access != GL_WRITE_ONLY && access != GL_READ_WRITE) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, + MakeUnique("MG_Impl/GLImpl", __func__, "Invalid image texture access.")); + return; + } + + SharedPtr textureObject; + if (texture != 0) { + if (!MG_State::pGLContext->ValidateTextureObject(texture)) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", __func__, "Texture name is not a texture object.")); + return; + } + textureObject = MG_State::pGLContext->GetTextureObject(texture); + } + + MG_State::pGLContext->GetImageTextureBinding(static_cast(unit)) + .Bind(textureObject, level, layered, layer, access, format); + + auto bindImageTexture = MG_Backend::gBackendFunctionsTable.GL.BindImageTexture; + if (!bindImageTexture) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, + "Backend does not support image texture binding.")); + return; + } + bindImageTexture(unit, texture, level, layered, layer, access, format); + } + void GenerateMipmap(GLenum target) { GenerateMipmap_Backend(target); } diff --git a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.h b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.h index 642a27ad..36729e2d 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.h +++ b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.h @@ -11,6 +11,8 @@ namespace MobileGL::MG_Impl::GLImpl { /* @INSERTION_POINT:FUNCTION_DECLARATION@ */ + void BindImageTexture(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, + GLenum format); void GenerateMipmap(GLenum target); void GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels); void TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, diff --git a/MobileGL/MG_State/GLState/Core.cpp b/MobileGL/MG_State/GLState/Core.cpp index 5d4bdfe1..08043405 100644 --- a/MobileGL/MG_State/GLState/Core.cpp +++ b/MobileGL/MG_State/GLState/Core.cpp @@ -203,6 +203,14 @@ namespace MobileGL::MG_State { return m_textureState.GetUnitObject(unit); } + ImageTextureBinding& GLContext::GetImageTextureBinding(Int unit) { + return m_textureState.GetImageTextureBinding(unit); + } + + const ImageTextureBinding& GLContext::GetImageTextureBinding(Int unit) const { + return m_textureState.GetImageTextureBinding(unit); + } + Bool GLContext::ValidateTextureName(Uint index) const { return m_textureState.ValidateName(index); } diff --git a/MobileGL/MG_State/GLState/Core.h b/MobileGL/MG_State/GLState/Core.h index 05783bc1..0347dcac 100644 --- a/MobileGL/MG_State/GLState/Core.h +++ b/MobileGL/MG_State/GLState/Core.h @@ -78,6 +78,8 @@ namespace MobileGL { const SharedPtr& CreateTextureObject(Uint index, TextureTarget target); void MarkTextureObjectForDeletion(Uint index); TextureUnit& GetTextureUnitObject(Int unit); + ImageTextureBinding& GetImageTextureBinding(Int unit); + const ImageTextureBinding& GetImageTextureBinding(Int unit) const; Bool ValidateTextureName(Uint index) const; Bool ValidateTextureObject(Uint index) const; Int GetActiveTextureUnit() const; diff --git a/MobileGL/MG_State/GLState/TextureState/TextureState.cpp b/MobileGL/MG_State/GLState/TextureState/TextureState.cpp index ffb0007f..439abe95 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureState.cpp +++ b/MobileGL/MG_State/GLState/TextureState/TextureState.cpp @@ -97,6 +97,11 @@ namespace MobileGL::MG_State::GLState { } } } + for (auto& imageBinding : m_imageTextureBindings) { + if (imageBinding.Texture == it->second) { + imageBinding.Bind(nullptr, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8); + } + } m_textureObjects.erase(it); } m_indexGenerator.Delete(index); @@ -109,6 +114,18 @@ namespace MobileGL::MG_State::GLState { return m_textureUnits[unit]; } + ImageTextureBinding& TextureState::GetImageTextureBinding(Int unit) { + MOBILEGL_ASSERT(unit >= 0 && unit < MAX_TEXTURE_IMAGE_UNITS, "Image unit is out of range: %d > %d", unit, + MAX_TEXTURE_IMAGE_UNITS - 1); + return m_imageTextureBindings[unit]; + } + + const ImageTextureBinding& TextureState::GetImageTextureBinding(Int unit) const { + MOBILEGL_ASSERT(unit >= 0 && unit < MAX_TEXTURE_IMAGE_UNITS, "Image unit is out of range: %d > %d", unit, + MAX_TEXTURE_IMAGE_UNITS - 1); + return m_imageTextureBindings[unit]; + } + Int TextureState::GetActiveTextureUnit() const { return m_activeTextureUnit; } diff --git a/MobileGL/MG_State/GLState/TextureState/TextureState.h b/MobileGL/MG_State/GLState/TextureState/TextureState.h index fe4fce28..5f5e4cc3 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureState.h +++ b/MobileGL/MG_State/GLState/TextureState/TextureState.h @@ -14,6 +14,27 @@ #include "TextureUnit.h" namespace MobileGL::MG_State::GLState { + struct ImageTextureBinding { + SharedPtr Texture; + GLint Level = 0; + GLboolean Layered = GL_FALSE; + GLint Layer = 0; + GLenum Access = GL_READ_ONLY; + GLenum Format = GL_RGBA8; + Uint16 Version = 0; + + void Bind(SharedPtr texture, GLint level, GLboolean layered, GLint layer, GLenum access, + GLenum format) { + Texture = Move(texture); + Level = level; + Layered = layered; + Layer = layer; + Access = access; + Format = format; + ++Version; + } + }; + class TextureState { public: static constexpr int MAX_TEXTURE_IMAGE_UNITS = 32; @@ -23,6 +44,8 @@ namespace MobileGL::MG_State::GLState { const SharedPtr& CreateTextureObject(Uint index, TextureTarget target); const SharedPtr& GetTextureObject(Uint index); TextureUnit& GetUnitObject(Int unit); + ImageTextureBinding& GetImageTextureBinding(Int unit); + const ImageTextureBinding& GetImageTextureBinding(Int unit) const; Int GetActiveTextureUnit() const; void SetActiveTextureUnit(Int unit); void MarkTextureObjectForDeletion(Uint index); @@ -32,6 +55,7 @@ namespace MobileGL::MG_State::GLState { private: Int m_activeTextureUnit = 0; Array m_textureUnits; + Array m_imageTextureBindings; IndexGenerator m_indexGenerator; UnorderedMap> m_textureObjects; }; diff --git a/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.cpp b/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.cpp index 41dcd350..bdcd4798 100644 --- a/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.cpp +++ b/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.cpp @@ -311,6 +311,7 @@ namespace MobileGL::MG_Util::BackendLoader { INIT_GLES_FUNC(glFramebufferParameteri) INIT_GLES_FUNC(glGetFramebufferParameteriv) INIT_GLES_FUNC(glGetProgramInterfaceiv) + INIT_GLES_FUNC(glShaderStorageBlockBinding) INIT_GLES_FUNC(glGetProgramResourceIndex) INIT_GLES_FUNC(glGetProgramResourceName) INIT_GLES_FUNC(glGetProgramResourceiv) diff --git a/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.h b/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.h index 17b0f884..bc67087b 100644 --- a/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.h +++ b/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.h @@ -447,6 +447,8 @@ namespace MobileGL { GL_FUNC_TYPEDEF(void, glGetFramebufferParameteriv, GLenum target, GLenum pname, GLint* params) GL_FUNC_TYPEDEF(void, glGetProgramInterfaceiv, GLuint program, GLenum programInterface, GLenum pname, GLint* params) + GL_FUNC_TYPEDEF(void, glShaderStorageBlockBinding, GLuint program, GLuint storageBlockIndex, + GLuint storageBlockBinding) GL_FUNC_TYPEDEF(GLuint, glGetProgramResourceIndex, GLuint program, GLenum programInterface, const GLchar* name) GL_FUNC_TYPEDEF(void, glGetProgramResourceName, GLuint program, GLenum programInterface, GLuint index, @@ -884,6 +886,7 @@ namespace MobileGL { GL_FUNC_DECL(glFramebufferParameteri) GL_FUNC_DECL(glGetFramebufferParameteriv) GL_FUNC_DECL(glGetProgramInterfaceiv) + GL_FUNC_DECL(glShaderStorageBlockBinding) GL_FUNC_DECL(glGetProgramResourceIndex) GL_FUNC_DECL(glGetProgramResourceName) GL_FUNC_DECL(glGetProgramResourceiv)