diff --git a/CMakeLists.txt b/CMakeLists.txt index db0a77ac..74c8593a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,6 +85,8 @@ set(SOURCE_FILES MobileGL/MG_Util/Converters/GLToMG/ProgramEnumConverter.cpp MobileGL/MG_Util/Converters/MGToMG/TextureEnumConverter.cpp + MobileGL/MG_Util/Classifiers/TextureEnumClassifier.cpp + MobileGL/MG_Util/ShaderTranspiler/ShaderCompiler.cpp MobileGL/MG_Util/ShaderTranspiler/SpvcSession.cpp MobileGL/MG_Util/ShaderTranspiler/ShaderSourceProcessor.cpp diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp index f9764f17..9f0cef42 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp @@ -1,6 +1,9 @@ #include "DirectGLES.h" #include "Utils.h" #include "Managers.h" +#include "MG_Util/Converters/GLToMG/TextureEnumConverter.h" +#include "MG_Util/Classifiers/TextureEnumClassifier.h" +#include "MG_Util/Metrics/TextureMetrics.h" #include #include #include @@ -471,6 +474,106 @@ namespace MobileGL::MG_Backend::DirectGLES { MG_External::GLES::glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); } + void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, + GLsizei height, GLint border) { + MGLOG_D("%s: Backend", __func__); + TextureImpl::SyncNeccessaryTextures(); + FramebufferImpl::SyncCurrentFBO(); + RenderStateImpl::SyncRenderState(); + + GLint realInternalFormat; + MG_External::GLES::glGetTexLevelParameteriv(target, level, GL_TEXTURE_INTERNAL_FORMAT, &realInternalFormat); + internalformat = (GLenum)realInternalFormat; + auto mglInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat); + + GLenum format = GL_DEPTH_COMPONENT; + GLenum type = GL_UNSIGNED_INT; + TextureImpl::GenerateTextureFormatInfo(mglInternalFormat, &internalformat, &format, &type); + TexturePixelDataType texturePixelDataType = MG_Util::ConvertGLEnumToTexturePixelDataType(type); + + bool isDepthFormat = MG_Util::IsDepthFormatInternalFormat( + MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat)); + + if (!isDepthFormat) { + MG_External::GLES::glCopyTexImage2D( + target, level, internalformat, x, y, width, height, border); + } else { + MGLOG_D("%s: Backend depth", __func__); + MG_External::GLES::glTexImage2D(target, level, (GLint)internalformat, width, height, border, format, type, nullptr); + FramebufferImpl::BackendFramebufferBindingProtector drawFboProtector(GL_DRAW_FRAMEBUFFER); + FramebufferImpl::BackendFramebufferBindingProtector readFboProtector(GL_READ_FRAMEBUFFER); + + FramebufferImpl::BackendFramebufferBindingProtector::BindTempFBO(FramebufferTarget::Draw); + GLint currentTex; + MG_External::GLES::glGetIntegerv(Utils::GetBindingQuery(target, false), ¤tTex); + MG_External::GLES::glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, target, currentTex, level); + if (MG_External::GLES::glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + // Protector will automatically revert to previous fbo states + return; + } + + MG_External::GLES::glBlitFramebuffer(x, y, x + width, y + height, 0, 0, width, height, GL_DEPTH_BUFFER_BIT, GL_NEAREST); + // Protector will automatically revert to previous fbo states + } + + // TODO: potential desync between MG_State and backend + auto activeUnit = + MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit()); + TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); + auto& bindingSlot = activeUnit.GetBindingSlot(textureTarget); + auto textureObject = bindingSlot.GetBoundObject(); + + + const SizeT bytesPerPixel = MG_Util::GetInputBytesPerPixel(mglInternalFormat, texturePixelDataType); + const SizeT totalBytes = width * height * bytesPerPixel; + + MG_State::GLState::MipmapLevelInput mipmap = + MG_State::GLState::MipmapLevelInput({width, height, 1}, level, false, 0, + {nullptr, totalBytes}); + + textureObject->SetInternalFormat(mglInternalFormat); + textureObject->SetMipmapLevel(mipmap); + } + + void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, + GLsizei width, GLsizei height) { + MGLOG_D("%s: Backend", __func__); + TextureImpl::SyncNeccessaryTextures(); + FramebufferImpl::SyncCurrentFBO(); + RenderStateImpl::SyncRenderState(); + + BindCurrentFBO(FramebufferTarget::Read); + + GLenum internalFormat; + MG_External::GLES::glGetTexLevelParameteriv(target, level, GL_TEXTURE_INTERNAL_FORMAT, (GLint *)&internalFormat); + + auto mglInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalFormat); + + bool isDepthFormat = MG_Util::IsDepthFormatInternalFormat(mglInternalFormat); + bool isStencilFormat = MG_Util::IsStencilFormatInternalFormat(mglInternalFormat); + + if (!isDepthFormat) { + MG_External::GLES::glCopyTexSubImage2D( + target, level, xoffset, yoffset, x, y, width, height); + } else { + MGLOG_D("%s: Backend depth", __func__); + FramebufferImpl::BackendFramebufferBindingProtector drawFboProtector(GL_DRAW_FRAMEBUFFER); + FramebufferImpl::BackendFramebufferBindingProtector readFboProtector(GL_READ_FRAMEBUFFER); + FramebufferImpl::BackendFramebufferBindingProtector::BindTempFBO(FramebufferTarget::Draw); + GLint currentTex; + MG_External::GLES::glGetIntegerv(Utils::GetBindingQuery(target, false), ¤tTex); + MG_External::GLES::glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, target, currentTex, level); + if (MG_External::GLES::glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + // Protector will automatically revert to previous fbo states + return; + } + + MG_External::GLES::glBlitFramebuffer(x, y, x + width, y + height, xoffset, yoffset, xoffset + width, yoffset + height, + GL_DEPTH_BUFFER_BIT | (isStencilFormat ? GL_STENCIL_BUFFER_BIT : 0), GL_NEAREST); + // Protector will automatically revert to previous fbo states + } + } + const GLubyte* GetString(GLenum name) { return MG_External::GLES::glGetString(name); } diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.h b/MobileGL/MG_Backend/DirectGLES/DirectGLES.h index 6f5f8bf4..6e4562e8 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.h +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.h @@ -16,5 +16,9 @@ namespace MobileGL::MG_Backend::DirectGLES { GLsizei drawcount, const GLint* basevertex); void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); + void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, + GLsizei height, GLint border); + void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, + GLsizei width, GLsizei height); const GLubyte* GetString(GLenum name); } // namespace MobileGL::MG_Backend::DirectGLES \ No newline at end of file diff --git a/MobileGL/MG_Backend/DirectGLES/Utils.cpp b/MobileGL/MG_Backend/DirectGLES/Utils.cpp index 7c515e81..92909231 100644 --- a/MobileGL/MG_Backend/DirectGLES/Utils.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Utils.cpp @@ -1,10 +1,12 @@ #include "DirectGLES.h" #include "Utils.h" #include "Managers.h" +#include "MG_Util/Converters/GLToMG/FramebufferEnumConverter.h" #include #include #include #include +#include namespace MobileGL::MG_Backend::DirectGLES { namespace BufferImpl { @@ -291,6 +293,21 @@ namespace MobileGL::MG_Backend::DirectGLES { BackendFramebufferBindingProtector::~BackendFramebufferBindingProtector() { MG_External::GLES::glBindFramebuffer(m_target, m_previousBinding); } + + GLuint BackendFramebufferBindingProtector::GetTempFBO(FramebufferTarget target) { + GLenum glTarget = MG_Util::ConvertFramebufferTargetToGLEnum(target); + GLuint& fbo = (glTarget == GL_DRAW_FRAMEBUFFER) ? s_tempDrawFBO : s_tempReadFBO; + if (fbo == 0) { + MG_External::GLES::glGenFramebuffers(1, &fbo); + } + return fbo; + } + + void BackendFramebufferBindingProtector::BindTempFBO(MobileGL::FramebufferTarget target) { + GLuint fbo = GetTempFBO(target); + GLenum glTarget = MG_Util::ConvertFramebufferTargetToGLEnum(target); + MG_External::GLES::glBindFramebuffer(glTarget, fbo); + } } // namespace FramebufferImpl namespace PrgramImpl { diff --git a/MobileGL/MG_Backend/DirectGLES/Utils.h b/MobileGL/MG_Backend/DirectGLES/Utils.h index 499f226e..6f911131 100644 --- a/MobileGL/MG_Backend/DirectGLES/Utils.h +++ b/MobileGL/MG_Backend/DirectGLES/Utils.h @@ -54,9 +54,13 @@ namespace MobileGL::MG_Backend::DirectGLES { ~BackendFramebufferBindingProtector(); + static GLuint GetTempFBO(FramebufferTarget target); + static void BindTempFBO(FramebufferTarget target); private: GLenum m_target; GLint m_previousBinding = 0; + inline static GLuint s_tempReadFBO = 0; + inline static GLuint s_tempDrawFBO = 0; }; } // namespace FramebufferImpl diff --git a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp index 97c50655..b779db2b 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp +++ b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp @@ -1,5 +1,9 @@ #include "GL_Texture.h" #include "GL/gl.h" +#include "Config.h" +#if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES +#include +#endif #include "MG_Util/Types.h" #include "Validators.h" #include "ProxyTexture.h" @@ -804,18 +808,22 @@ namespace MobileGL { // TODO: implement } - void CopyTexSubImage2D_State(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, - GLsizei width, GLsizei height) { - // TODO: implement + void CopyTexSubImage2D_Backend(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, + GLsizei width, GLsizei height) { +#if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES + MG_Backend::DirectGLES::CopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); +#endif } void CopyTexSubImage1D_State(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) { // TODO: implement } - void CopyTexImage2D_State(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, - GLsizei height, GLint border) { - // TODO: implement + void CopyTexImage2D_Backend(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, + GLsizei height, GLint border) { +#if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES + MG_Backend::DirectGLES::CopyTexImage2D(target, level, internalformat, x, y, width, height, border); +#endif } void CopyTexImage1D_State(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, @@ -1004,7 +1012,7 @@ namespace MobileGL { void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) { - CopyTexSubImage2D_State(target, level, xoffset, yoffset, x, y, width, height); + CopyTexSubImage2D_Backend(target, level, xoffset, yoffset, x, y, width, height); } void CopyTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) { @@ -1013,7 +1021,7 @@ namespace MobileGL { void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) { - CopyTexImage2D_State(target, level, internalformat, x, y, width, height, border); + CopyTexImage2D_Backend(target, level, internalformat, x, y, width, height, border); } void CopyTexImage1D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, diff --git a/MobileGL/MG_Util/Classifiers/TextureEnumClassifier.cpp b/MobileGL/MG_Util/Classifiers/TextureEnumClassifier.cpp new file mode 100644 index 00000000..38feae4d --- /dev/null +++ b/MobileGL/MG_Util/Classifiers/TextureEnumClassifier.cpp @@ -0,0 +1,32 @@ +#include "TextureEnumClassifier.h" + +namespace MobileGL { + namespace MG_Util { + bool IsDepthFormatInternalFormat(TextureInternalFormat internalformat) { + switch (internalformat) { + case TextureInternalFormat::DepthComponent16: + case TextureInternalFormat::DepthComponent24: + case TextureInternalFormat::DepthComponent32: + case TextureInternalFormat::DepthComponent32F: + case TextureInternalFormat::Depth24Stencil8: + case TextureInternalFormat::Depth32FStencil8: + case TextureInternalFormat::DepthComponent: + case TextureInternalFormat::DepthStencil: + return true; + default: + return false; + } + } + + bool IsStencilFormatInternalFormat(TextureInternalFormat internalformat) { + switch (internalformat) { + case TextureInternalFormat::Depth24Stencil8: + case TextureInternalFormat::Depth32FStencil8: + case TextureInternalFormat::DepthStencil: + return true; + default: + return false; + } + } + } // namespace MG_Util +} // namespace MobileGL \ No newline at end of file diff --git a/MobileGL/MG_Util/Classifiers/TextureEnumClassifier.h b/MobileGL/MG_Util/Classifiers/TextureEnumClassifier.h new file mode 100644 index 00000000..8737e562 --- /dev/null +++ b/MobileGL/MG_Util/Classifiers/TextureEnumClassifier.h @@ -0,0 +1,10 @@ +#pragma once +#include +#include + +namespace MobileGL { + namespace MG_Util { + bool IsDepthFormatInternalFormat(TextureInternalFormat internalformat); + bool IsStencilFormatInternalFormat(TextureInternalFormat internalformat); + } // namespace MG_Util +} // namespace MobileGL \ No newline at end of file