From e230e55ed4122b6cb0f502519e8c1d14254a996c Mon Sep 17 00:00:00 2001 From: assiduous Date: Sun, 1 Oct 2023 20:46:22 -0700 Subject: [PATCH] Fixed staging buffers in WebGL (fix #412) --- Common/interface/StringTools.hpp | 2 +- .../include/BufferGLImpl.hpp | 7 ++++++ Graphics/GraphicsEngineOpenGL/include/pch.h | 3 ++- .../GraphicsEngineOpenGL/src/BufferGLImpl.cpp | 22 ++++++++++++++++++- 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/Common/interface/StringTools.hpp b/Common/interface/StringTools.hpp index f2adcfd67..90dd3ea8c 100644 --- a/Common/interface/StringTools.hpp +++ b/Common/interface/StringTools.hpp @@ -205,7 +205,7 @@ inline size_t CountFloatNumberChars(const char* Str) /// For each chunk, calls the Handler. /// /// \note This function is used to split long messages on Android to avoid -/// trunction in logcat. +/// truncation in logcat. template void SplitLongString(IterType Start, IterType End, size_t MaxChunkLen, size_t NewLineSearchLen, HandlerType&& Handler) { diff --git a/Graphics/GraphicsEngineOpenGL/include/BufferGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/BufferGLImpl.hpp index 87bb1ea88..0fbaa4e09 100644 --- a/Graphics/GraphicsEngineOpenGL/include/BufferGLImpl.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/BufferGLImpl.hpp @@ -27,6 +27,8 @@ #pragma once +#include + #include "EngineGLImplTraits.hpp" #include "BufferBase.hpp" #include "BufferViewGLImpl.hpp" // Required by BufferBase @@ -92,6 +94,11 @@ class BufferGLImpl final : public BufferBase, public AsyncWr GLObjectWrappers::GLBufferObj m_GlBuffer; const Uint32 m_BindTarget; const GLenum m_GLUsageHint; + +#if PLATFORM_EMSCRIPTEN + // Used for devices that don't support glMapBufferRange (currently, Emscripten) + std::vector m_MappedData; +#endif }; void BufferGLImpl::BufferMemoryBarrier(MEMORY_BARRIER RequiredBarriers, GLContextState& GLState) diff --git a/Graphics/GraphicsEngineOpenGL/include/pch.h b/Graphics/GraphicsEngineOpenGL/include/pch.h index c32ece35e..b94c07c7c 100644 --- a/Graphics/GraphicsEngineOpenGL/include/pch.h +++ b/Graphics/GraphicsEngineOpenGL/include/pch.h @@ -1,5 +1,5 @@ /* - * Copyright 2019-2022 Diligent Graphics LLC + * Copyright 2019-2023 Diligent Graphics LLC * Copyright 2015-2019 Egor Yusov * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -111,6 +111,7 @@ #elif PLATFORM_EMSCRIPTEN +# include # include # include "GLStubsEmscripten.h" diff --git a/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp index 6595f6b86..259009dd0 100644 --- a/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2019-2022 Diligent Graphics LLC + * Copyright 2019-2023 Diligent Graphics LLC * Copyright 2015-2019 Egor Yusov * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -277,6 +277,18 @@ void BufferGLImpl::MapRange(GLContextState& CtxState, MAP_TYPE MapType, Uint32 M constexpr bool ResetVAO = true; CtxState.BindBuffer(m_BindTarget, m_GlBuffer, ResetVAO); +#if PLATFORM_EMSCRIPTEN + // Emscripten does not support mapping buffers for reading + if (MapType == MAP_READ) + { + m_MappedData.resize(static_cast(Length)); + glGetBufferSubData(m_BindTarget, StaticCast(Offset), StaticCast(Length), m_MappedData.data()); + CHECK_GL_ERROR("glGetBufferSubData() failed"); + pMappedData = m_MappedData.data(); + return; + } +#endif + // !!!WARNING!!! GL_MAP_UNSYNCHRONIZED_BIT is not the same thing as MAP_FLAG_DO_NOT_WAIT. // If GL_MAP_UNSYNCHRONIZED_BIT flag is set, OpenGL will not attempt to synchronize operations // on the buffer. This does not mean that map will fail if the buffer still in use. It is thus @@ -328,6 +340,14 @@ void BufferGLImpl::MapRange(GLContextState& CtxState, MAP_TYPE MapType, Uint32 M void BufferGLImpl::Unmap(GLContextState& CtxState) { +#if PLATFORM_EMSCRIPTEN + if (!m_MappedData.empty()) + { + m_MappedData.clear(); + return; + } +#endif + constexpr bool ResetVAO = true; CtxState.BindBuffer(m_BindTarget, m_GlBuffer, ResetVAO); auto Result = glUnmapBuffer(m_BindTarget);