Merge branch 'Feat/Backend-Direct-GLES' into dev

This commit is contained in:
BZLZHH
2026-02-05 22:00:49 +08:00
68 changed files with 2283 additions and 1731 deletions
+51 -28
View File
@@ -13,10 +13,32 @@ if (ANDROID)
endif()
if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug" OR MOBILEGL_FORCE_RELEASE_OPT)
# Check if ThinLTO or LTO is suppported
include(CheckIPOSupported)
include(CheckCCompilerFlag)
include(CheckCXXCompilerFlag)
check_ipo_supported(RESULT LTOSupported OUTPUT LTOError)
if (LTOSupported)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
check_c_compiler_flag("-flto" HAS_LTO_C)
check_cxx_compiler_flag("-flto" HAS_LTO_CXX)
if (LTOSupported OR (HAS_LTO_C AND HAS_LTO_CXX))
# Check ThinLTO
check_c_compiler_flag("-flto=thin" HAS_THINLTO_C)
check_cxx_compiler_flag("-flto=thin" HAS_THINLTO_CXX)
if (HAS_THINLTO_C AND HAS_THINLTO_CXX)
message(STATUS "ThinLTO supported, using -flto=thin")
add_compile_options(-flto=thin)
add_link_options(-flto=thin)
else()
# ThinLTO is not supported
message(STATUS "ThinLTO not available, fallback to CMAKE IPO")
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
else()
message(STATUS "IPO not supported: ${LTOError}")
endif()
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang" AND NOT MATCHES "AppleClang")
@@ -103,7 +125,9 @@ set(SOURCE_FILES
MobileGL/MG_Util/Debug/Log.cpp
MobileGL/MG_Util/Math/VectorTypes.cpp
MobileGL/MG_Util/Metrics/TextureMetrics.cpp
MobileGL/MG_Util/Metrics/BufferMetrics.cpp
MobileGL/MG_Util/Converters/GLToStr/GLEnumConverter.cpp
@@ -248,33 +272,35 @@ target_link_libraries(${CMAKE_PROJECT_NAME}
${MOBILEGL_LINK_LIBRARIES}
)
add_library(${CMAKE_PROJECT_NAME}_s STATIC
${SOURCE_FILES}
)
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set_target_properties(${CMAKE_PROJECT_NAME}_s PROPERTIES
C_VISIBILITY_PRESET default
CXX_VISIBILITY_PRESET default
VISIBILITY_INLINES_HIDDEN OFF
if(NOT ANDROID)
add_library(${CMAKE_PROJECT_NAME}_s STATIC
${SOURCE_FILES}
)
else()
set_target_properties(${CMAKE_PROJECT_NAME}_s PROPERTIES
C_VISIBILITY_PRESET hidden
CXX_VISIBILITY_PRESET hidden
VISIBILITY_INLINES_HIDDEN ON
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set_target_properties(${CMAKE_PROJECT_NAME}_s PROPERTIES
C_VISIBILITY_PRESET default
CXX_VISIBILITY_PRESET default
VISIBILITY_INLINES_HIDDEN OFF
)
else()
set_target_properties(${CMAKE_PROJECT_NAME}_s PROPERTIES
C_VISIBILITY_PRESET hidden
CXX_VISIBILITY_PRESET hidden
VISIBILITY_INLINES_HIDDEN ON
)
endif()
target_include_directories(${CMAKE_PROJECT_NAME}_s PUBLIC
${MOBILEGL_INCLUDE_DIR}
)
target_link_libraries(${CMAKE_PROJECT_NAME}_s
PRIVATE
${MOBILEGL_LINK_LIBRARIES}
)
endif()
target_include_directories(${CMAKE_PROJECT_NAME}_s PUBLIC
${MOBILEGL_INCLUDE_DIR}
)
target_link_libraries(${CMAKE_PROJECT_NAME}_s
PRIVATE
${MOBILEGL_LINK_LIBRARIES}
)
if (TRACY_ENABLE)
target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC Tracy::TracyClient)
target_link_libraries(${CMAKE_PROJECT_NAME}_s PUBLIC Tracy::TracyClient)
@@ -287,9 +313,6 @@ if (ANDROID)
android
log
)
target_link_libraries(${CMAKE_PROJECT_NAME}_s PUBLIC
android
log)
endif()
if (MOBILEGL_BUILD_TEST)
+182 -302
View File
@@ -7,6 +7,9 @@
// End of Source File Header
#include "DirectGLES.h"
#include "GLES3/gl32.h"
#include "MG_State/GLState/SamplerState/SamplerObject.h"
#include "MG_Util/Debug/Log.h"
#include "Utils.h"
#include "Managers.h"
#include <MG_Util/Converters/GLToMG/TextureEnumConverter.h>
@@ -86,6 +89,20 @@ namespace MobileGL::MG_Backend::DirectGLES {
// TODO: deletion for deleted objects
namespace BufferImpl {
void CreateAndSyncBufferObject(SharedPtr<MG_State::GLState::BufferObject>& bufferObject) {
if (!(bufferObject->GetChangeBits() & BufferChangeBits::DirtyBit)) return;
const auto& backendBufferIt = g_backendBufferObjects.find(bufferObject);
SharedPtr<BackendBufferObject> backendBufferObject;
if (backendBufferIt == g_backendBufferObjects.end()) {
backendBufferObject = MakeShared<BackendBufferObject>();
g_backendBufferObjects[bufferObject] = backendBufferObject;
} else {
backendBufferObject = backendBufferIt->second;
}
backendBufferObject->SyncToBackend(bufferObject);
}
void SyncNeccessaryBuffers(Bool includeIBO = false, Bool includeIndirectBuffer = false) {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
@@ -94,7 +111,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
// 1.VBO 2.IBO (if needed) 3.UBO 4.IndirectBuffer (if needed) 5.SSBO (TODO)
// PBO is not needed since it should be handled in frontend
Vector<SharedPtr<MG_State::GLState::BufferObject>> buffersToSync;
// static Vector<SharedPtr<MG_State::GLState::BufferObject>> buffersToSync;
// buffersToSync.clear();
const auto& currentVAOObject = MG_State::pGLContext->GetBoundVertexArray();
if (!currentVAOObject) {
MGLOG_E("No VAO is currently bound, cannot sync necessary buffers.");
@@ -104,35 +123,26 @@ namespace MobileGL::MG_Backend::DirectGLES {
// VBO
for (const auto& attrib : currentVAOObject->GetAllAttributes()) {
if (!attrib.Enabled) continue;
const auto& bufferObject = attrib.Buffer;
auto bufferObject = attrib.Buffer;
if (bufferObject) {
const auto& end = buffersToSync.end();
if (std::find(buffersToSync.begin(), end, bufferObject) == end) {
buffersToSync.push_back(bufferObject);
}
CreateAndSyncBufferObject(bufferObject);
}
}
// IBO
if (includeIBO) {
const auto& possibleIBO = currentVAOObject->GetIndexBufferBindingSlot().GetBoundObject();
auto possibleIBO = currentVAOObject->GetIndexBufferBindingSlot().GetBoundObject();
if (possibleIBO) {
const auto& end = buffersToSync.end();
if (std::find(buffersToSync.begin(), end, possibleIBO) == end) {
buffersToSync.push_back(possibleIBO);
}
CreateAndSyncBufferObject(possibleIBO);
}
}
// Indirect Buffer Object
if (includeIndirectBuffer) {
const auto& possibleIndirectBuffer =
auto possibleIndirectBuffer =
MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
if (possibleIndirectBuffer) {
const auto& end = buffersToSync.end();
if (std::find(buffersToSync.begin(), end, possibleIndirectBuffer) == end) {
buffersToSync.push_back(possibleIndirectBuffer);
}
CreateAndSyncBufferObject(possibleIndirectBuffer);
}
}
@@ -142,30 +152,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
auto& point = MG_State::pGLContext->GetBufferBindingPoint(BufferTarget::Uniform, i);
auto obj = point.GetBoundObject();
if (obj) {
const auto& end = buffersToSync.end();
if (std::find(buffersToSync.begin(), end, obj) == end) {
buffersToSync.push_back(obj);
}
CreateAndSyncBufferObject(obj);
}
}
// Do real sync
for (auto& bufferObject : buffersToSync) {
const auto& backendBufferIt = g_backendBufferObjects.find(bufferObject);
SharedPtr<BackendBufferObject> backendBufferObject;
if (backendBufferIt == g_backendBufferObjects.end()) {
backendBufferObject = MakeShared<BackendBufferObject>();
g_backendBufferObjects[bufferObject] = backendBufferObject;
} else {
backendBufferObject = backendBufferIt->second;
}
backendBufferObject->SyncToBackend(bufferObject);
}
}
} // namespace BufferImpl
namespace VertexArrayImpl {
void SyncCurrentVAO(Bool needDivisor) {
void SyncCurrentVAO() {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
@@ -183,7 +177,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
} else {
backendVAOObject = backendVAOIt->second;
}
backendVAOObject->SyncToBackend(currentVAOObject, needDivisor);
backendVAOObject->SyncToBackend(currentVAOObject);
}
} // namespace VertexArrayImpl
@@ -201,7 +195,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
} else {
backendTextureObject = backendTextureIt->second;
}
backendTextureObject->SyncToBackend(textureObject);
backendTextureObject->SyncTextureParamsToBackend(textureObject);
backendTextureObject->SyncBuiltinSamplerToBackend(textureObject);
backendTextureObject->SyncMipmapsToBackend(textureObject);
return backendTextureObject;
}
@@ -213,21 +209,13 @@ namespace MobileGL::MG_Backend::DirectGLES {
// 1. textures bound to texture units (TODO: only sync ones that are used in current program)
// 2. textures used in current FBO
// 3. textures bound to image units (TODO)
constexpr SizeT TextureTargetCount = static_cast<SizeT>(TextureTarget::TextureTargetCount);
std::bitset<TextureTargetCount> dirtyTextureTargetBits;
Vector<SharedPtr<MG_State::GLState::ITextureObject>> texturesToSync;
for (int index = 0; index < MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS; ++index) {
auto& unit = MG_State::pGLContext->GetTextureUnitObject(index);
for (const auto& bindingSlot : unit.GetAllBindingSlots()) {
const auto& textureObject = bindingSlot.GetBoundObject();
auto textureObject = bindingSlot.GetBoundObject();
if (textureObject) {
const auto& end = texturesToSync.end();
if (std::find(texturesToSync.begin(), end, textureObject) == end) {
texturesToSync.push_back(textureObject);
dirtyTextureTargetBits.set(static_cast<SizeT>(textureObject->GetTarget()));
}
SyncTextureObjectToBackend(textureObject);
}
}
}
@@ -235,34 +223,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
const auto& currentFBO =
MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
if (currentFBO) {
for (const auto& attachment : currentFBO->GetAllAttachments()) {
for (const auto& attachment : currentFBO->GetAllAttachmentObjects()) {
if (!attachment.IsTexture()) continue;
const auto& textureObject = attachment.GetTexture();
auto textureObject = attachment.GetTexture();
if (textureObject) {
const auto& end = texturesToSync.end();
if (std::find(texturesToSync.begin(), end, textureObject) == end) {
texturesToSync.push_back(textureObject);
dirtyTextureTargetBits.set(static_cast<SizeT>(textureObject->GetTarget()));
}
SyncTextureObjectToBackend(textureObject);
}
}
}
BufferImpl::BackendBufferBindingProtector pixelUnpackProtector =
BufferImpl::BackendBufferBindingProtector(GL_PIXEL_UNPACK_BUFFER);
Vector<BackendTextureBindingProtector> textureBindingProtectors;
for (SizeT target = 0; target < TextureTargetCount; ++target) {
if (dirtyTextureTargetBits[target]) {
textureBindingProtectors.emplace_back(
MG_Util::ConvertTextureTargetToGLEnum(static_cast<TextureTarget>(target)));
}
}
// Do real sync
for (auto& textureObject : texturesToSync) {
SyncTextureObjectToBackend(textureObject);
}
}
} // namespace TextureImpl
@@ -276,7 +244,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
MG_State::GLState::FramebufferObject* lastUpdatedFBO = nullptr;
for (auto target : fboTargets) {
auto currentFBO = MG_State::pGLContext->GetFramebufferBindingSlot(target).GetBoundObject();
auto slot = MG_State::pGLContext->GetFramebufferBindingSlot(target);
auto version = slot.GetVersion();
if (version == g_fboBindVersions[SizeT(target)]) continue;
auto currentFBO = slot.GetBoundObject();
if (!currentFBO) {
MGLOG_E("No FBO is currently bound, cannot sync current FBO.");
@@ -303,39 +275,51 @@ namespace MobileGL::MG_Backend::DirectGLES {
backendFBOObject->SyncToBackend(currentFBO, target);
}
backendFBOObject->Bind(target);
lastUpdatedFBO = currentFBO.get();
}
}
} // namespace FramebufferImpl
namespace RenderStateImpl {
static Uint16 g_syncedRenderStateVersion = 0;
static RenderStateParameters g_syncedRenderStateParameters;
void SyncRenderState() {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
MG_External::GLES::glViewport(
MG_State::pGLContext->GetViewport().x(), MG_State::pGLContext->GetViewport().y(),
MG_State::pGLContext->GetViewport().z(), MG_State::pGLContext->GetViewport().w());
Uint16 currentRenderStateVersion = MG_State::pGLContext->GetRenderStateParametersVersion();
if (currentRenderStateVersion == g_syncedRenderStateVersion) return;
const auto& parameters = MG_State::pGLContext->GetRenderStateParameters();
if (parameters.Viewport != g_syncedRenderStateParameters.Viewport) {
MG_External::GLES::glViewport(parameters.Viewport.x(), parameters.Viewport.y(), parameters.Viewport.z(),
parameters.Viewport.w());
}
#define SYNC_CAPABILITY(cap_mg, cap_gl) \
if (MG_State::pGLContext->IsCapabilityEnabled(cap_mg)) { \
MG_External::GLES::glEnable(cap_gl); \
} else { \
MG_External::GLES::glDisable(cap_gl); \
if (parameters.cap_mg##Enabled != g_syncedRenderStateParameters.cap_mg##Enabled) { \
if (parameters.cap_mg##Enabled) { \
MG_External::GLES::glEnable(cap_gl); \
} else { \
MG_External::GLES::glDisable(cap_gl); \
} \
}
SYNC_CAPABILITY(CapabilityInput::Blend, GL_BLEND);
SYNC_CAPABILITY(CapabilityInput::DepthTest, GL_DEPTH_TEST);
SYNC_CAPABILITY(CapabilityInput::ScissorTest, GL_SCISSOR_TEST);
SYNC_CAPABILITY(CapabilityInput::CullFace, GL_CULL_FACE);
SYNC_CAPABILITY(Blend, GL_BLEND);
SYNC_CAPABILITY(DepthTest, GL_DEPTH_TEST);
SYNC_CAPABILITY(ScissorTest, GL_SCISSOR_TEST);
SYNC_CAPABILITY(CullFace, GL_CULL_FACE);
#undef SYNC_CAPABILITY
const auto& ToGLBoolean = [](Bool b) -> GLboolean { return b ? GL_TRUE : GL_FALSE; };
{ // Blend func
BlendFactor srcRGB, dstRGB, srcAlpha, dstAlpha;
MG_State::pGLContext->GetBlendFunc(srcRGB, dstRGB, srcAlpha, dstAlpha);
if (parameters.SrcFactorRGB != g_syncedRenderStateParameters.SrcFactorRGB ||
parameters.DstFactorRGB != g_syncedRenderStateParameters.DstFactorRGB ||
parameters.SrcFactorAlpha != g_syncedRenderStateParameters.SrcFactorAlpha ||
parameters.DstFactorAlpha != g_syncedRenderStateParameters.DstFactorAlpha) { // Blend func
const BlendFactor &srcRGB = parameters.SrcFactorRGB, &dstRGB = parameters.DstFactorRGB,
&srcAlpha = parameters.SrcFactorAlpha, &dstAlpha = parameters.DstFactorAlpha;
MG_External::GLES::glBlendFuncSeparate(
MG_Util::ConvertBlendFactorToGLEnum(srcRGB), MG_Util::ConvertBlendFactorToGLEnum(dstRGB),
@@ -343,33 +327,48 @@ namespace MobileGL::MG_Backend::DirectGLES {
}
{ // Blend equation
DepthTestFunc df = MG_State::pGLContext->GetDepthFunc();
MG_External::GLES::glDepthFunc(MG_Util::ConvertDepthTestFuncToGLEnum(df));
MG_External::GLES::glDepthMask(MG_State::pGLContext->GetDepthMask() ? GL_TRUE : GL_FALSE);
if (parameters.DepthFunc != g_syncedRenderStateParameters.DepthFunc) {
MG_External::GLES::glDepthFunc(MG_Util::ConvertDepthTestFuncToGLEnum(parameters.DepthFunc));
}
if (parameters.DepthMask != g_syncedRenderStateParameters.DepthMask) {
MG_External::GLES::glDepthMask(parameters.DepthMask ? GL_TRUE : GL_FALSE);
}
}
{ // Color mask
BoolVec4 colorMask = MG_State::pGLContext->GetColorMask();
MG_External::GLES::glColorMask(ToGLBoolean(colorMask.x()), ToGLBoolean(colorMask.y()),
ToGLBoolean(colorMask.z()), ToGLBoolean(colorMask.w()));
if (parameters.ColorMask != g_syncedRenderStateParameters.ColorMask) {
const BoolVec4& colorMask = parameters.ColorMask;
MG_External::GLES::glColorMask(ToGLBoolean(colorMask.x()), ToGLBoolean(colorMask.y()),
ToGLBoolean(colorMask.z()), ToGLBoolean(colorMask.w()));
}
}
{ // Clear values
const FloatVec4& clearCol = MG_State::pGLContext->GetClearColor();
MG_External::GLES::glClearColor(clearCol.x(), clearCol.y(), clearCol.z(), clearCol.w());
MG_External::GLES::glClearDepthf(MG_State::pGLContext->GetClearDepth());
if (parameters.ClearColor != g_syncedRenderStateParameters.ClearColor) {
const FloatVec4& clearCol = parameters.ClearColor;
MG_External::GLES::glClearColor(clearCol.x(), clearCol.y(), clearCol.z(), clearCol.w());
}
if (parameters.ClearDepth != g_syncedRenderStateParameters.ClearDepth) {
MG_External::GLES::glClearDepthf(parameters.ClearDepth);
}
}
{ // Cull face mode
CullFaceMode cfm = MG_State::pGLContext->GetCullFaceMode();
MG_External::GLES::glCullFace(MG_Util::ConvertCullFaceModeToGLEnum(cfm));
if (parameters.CullFaceModeSetting != g_syncedRenderStateParameters.CullFaceModeSetting) {
const CullFaceMode& cfm = parameters.CullFaceModeSetting;
MG_External::GLES::glCullFace(MG_Util::ConvertCullFaceModeToGLEnum(cfm));
}
}
{ // Scissor box
const IntVec4& scissorBox = MG_State::pGLContext->GetScissorBox();
MG_External::GLES::glScissor(scissorBox.x(), scissorBox.y(), scissorBox.z(), scissorBox.w());
if (parameters.ScissorBox != g_syncedRenderStateParameters.ScissorBox) {
const IntVec4& scissorBox = parameters.ScissorBox;
MG_External::GLES::glScissor(scissorBox.x(), scissorBox.y(), scissorBox.z(), scissorBox.w());
}
}
g_syncedRenderStateVersion = currentRenderStateVersion;
g_syncedRenderStateParameters = parameters;
}
} // namespace RenderStateImpl
@@ -402,7 +401,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
const auto& currentFBO = MG_State::pGLContext->GetFramebufferBindingSlot(target).GetBoundObject();
auto& slot = MG_State::pGLContext->GetFramebufferBindingSlot(target);
if (slot.GetVersion() == FramebufferImpl::g_fboBindVersions[(SizeT)target]) return;
const auto& currentFBO = slot.GetBoundObject();
if (currentFBO && currentFBO != MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo->defaultFBO) {
const auto& backendFBOIt = FramebufferImpl::g_backendFramebufferObjects.find(currentFBO);
if (backendFBOIt != FramebufferImpl::g_backendFramebufferObjects.end()) {
@@ -423,7 +425,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
BufferImpl::SyncNeccessaryBuffers(syncBit & DrawSyncBit::IndexBuffer, syncBit & DrawSyncBit::IndirectBuffer);
VertexArrayImpl::SyncCurrentVAO(syncBit & DrawSyncBit::Instancing);
VertexArrayImpl::SyncCurrentVAO();
TextureImpl::SyncNeccessaryTextures();
FramebufferImpl::SyncCurrentFBO();
PrgramImpl::SyncCurrentProgram();
@@ -454,8 +456,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
for (Int unit = 0; unit < maxTextureUnits; ++unit) {
auto& textureUnit = MG_State::pGLContext->GetTextureUnitObject(unit);
MG_External::GLES::glActiveTexture(GL_TEXTURE0 + unit);
for (const auto& bindingSlot : textureUnit.GetAllBindingSlots()) {
const auto& textureObject = bindingSlot.GetBoundObject();
if (!textureObject) continue;
@@ -471,18 +471,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
if (backendTextureIt == TextureImpl::g_backendTextureObjects.end()) continue;
GLenum targetGL = MG_Util::ConvertTextureTargetToGLEnum(target);
backendTextureIt->second->Bind(targetGL);
backendTextureIt->second->Bind(targetGL, unit);
}
// Bind sampler object
// Bind sampler object if necessary
const auto& samplerObject = textureUnit.GetSamplerObject();
if (samplerObject) {
const auto& backendSamplerIt = SamplerImpl::g_backendSamplerObjects.find(samplerObject);
if (backendSamplerIt != SamplerImpl::g_backendSamplerObjects.end()) {
backendSamplerIt->second->Bind(unit);
}
} else {
MG_External::GLES::glBindSampler(unit, 0);
}
}
}
@@ -586,7 +586,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
}
backendSamplerObject->SyncToBackend(samplerObject);
} else {
MG_External::GLES::glBindSampler(unit, 0);
SamplerImpl::UnbindSampler(unit);
}
}
}
@@ -778,22 +778,21 @@ namespace MobileGL::MG_Backend::DirectGLES {
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
});
MGLOG_D("ES %s(%d, %d, %d, %d, %d, %d, %d, %d, 0x%x, %s)", __func__, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask,
MG_Util::ConvertGLEnumToString(filter).c_str());
MGLOG_D("ES %s(%d, %d, %d, %d, %d, %d, %d, %d, 0x%x, %s)", __func__, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
dstX1, dstY1, mask, MG_Util::ConvertGLEnumToString(filter).c_str());
MG_External::GLES::glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
});
}
bool UpdateTextureBindingAtTarget(GLenum target) {
Bool UpdateTextureBindingAtTarget(GLenum target) {
#ifdef TRACY_ENABLE
ZoneScopedNC(__func__, TRACY_ZONECOLOR_BACKEND);
#endif
auto unit = MG_State::pGLContext->GetActiveTextureUnit();
auto& textureUnit = MG_State::pGLContext->GetTextureUnitObject(unit);
MG_External::GLES::glActiveTexture(GL_TEXTURE0 + unit);
auto textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
if (!TextureImpl::IsSupportedTextureTarget(textureTarget)) {
MOBILEGL_ASSERT(false, " Texture target %s is not supported, skipping.",
@@ -817,15 +816,38 @@ namespace MobileGL::MG_Backend::DirectGLES {
} else {
backendTextureObject = backendTextureIt->second;
}
backendTextureObject->Bind(target);
backendTextureObject->Bind(target, unit);
}
return true;
}
static GLuint s_prevDrawFBO = 0;
void BindTempDrawFBO() {
MGLOG_D("%s: Binding temporary FBO for operations like CopyTexImage2D that require framebuffer binding, "
"previous draw FBO=%u",
__func__, s_prevDrawFBO);
static GLuint tempFBO = 0;
if (!tempFBO) {
MG_External::GLES::glGenFramebuffers(1, &tempFBO);
}
MG_External::GLES::glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, (GLint*)&s_prevDrawFBO);
MG_External::GLES::glBindFramebuffer(GL_DRAW_FRAMEBUFFER, tempFBO);
}
void RestoreDrawFBOFromTemp() {
MGLOG_D("%s: Restoring previous draw FBO=%u", __func__, s_prevDrawFBO);
MG_External::GLES::glBindFramebuffer(GL_DRAW_FRAMEBUFFER, s_prevDrawFBO);
}
class TempFBOBinder {
public:
TempFBOBinder() { BindTempDrawFBO(); }
~TempFBOBinder() { RestoreDrawFBOFromTemp(); }
};
void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width,
GLsizei height, GLint border) {
#if MOBILEGL_LOG_ACTIVE_LEVEL <= MOBILEGL_LOG_LEVEL_DEBUG
DebugImpl::OpenGLScopeMarker marker(__func__);
DebugImpl::OpenGLScopeMarker marker(__func__);
#endif
DebugImpl::ErrorLopper errorLopper;
MGLOG_D("%s: Backend", __func__);
@@ -841,31 +863,36 @@ namespace MobileGL::MG_Backend::DirectGLES {
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
});
if (!UpdateTextureBindingAtTarget(target)) return;
if (!UpdateTextureBindingAtTarget(target))
// Bind necessary FBO and texture
BindCurrentFBO(FramebufferTarget::Read);
Uint activeTextureUnit = MG_State::pGLContext->GetActiveTextureUnit();
const auto& textureObject = MG_State::pGLContext->GetTextureUnitObject(activeTextureUnit)
.GetBindingSlot(MG_Util::ConvertGLEnumToTextureTarget(target))
.GetBoundObject();
const auto& backendTextureIt = TextureImpl::g_backendTextureObjects.find(textureObject);
if (backendTextureIt == TextureImpl::g_backendTextureObjects.end()) {
MGLOG_E("CopyTexSubImage2D: No backend texture found for texture %u.",
textureObject ? textureObject->GetExternalIndex() : 0);
return;
}
backendTextureIt->second->Bind(target, activeTextureUnit);
// GLint realInternalFormat;
// MG_External::GLES::glGetTexLevelParameteriv(target, level, GL_TEXTURE_INTERNAL_FORMAT, &realInternalFormat);
// errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) {
// MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
// });
// internalformat = (GLenum)realInternalFormat;
auto mglInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat);
auto mgInternalFormat = textureObject->GetFormat();
GLenum format = GL_DEPTH_COMPONENT;
GLenum type = GL_UNSIGNED_INT;
TextureImpl::GenerateTextureFormatInfo(mglInternalFormat, &internalformat, &format, &type);
MOBILEGL_ASSERT(format != GL_NONE && type != GL_NONE, "%s: cannot GenerateTextureFormatInfo(%s): out internalformat=%s, format=%s, type=%s",
MG_Util::ConvertTextureInternalFormatToString(mglInternalFormat).c_str(),
TextureImpl::GenerateTextureFormatInfo(mgInternalFormat, &internalformat, &format, &type);
MOBILEGL_ASSERT(format != GL_NONE && type != GL_NONE,
"%s: cannot GenerateTextureFormatInfo(%s): out internalformat=%s, format=%s, type=%s",
MG_Util::ConvertTextureInternalFormatToString(mgInternalFormat).c_str(),
MG_Util::ConvertGLEnumToString(internalformat).c_str(),
MG_Util::ConvertGLEnumToString(format).c_str(),
MG_Util::ConvertGLEnumToString(type).c_str());
MG_Util::ConvertGLEnumToString(format).c_str(), MG_Util::ConvertGLEnumToString(type).c_str());
TexturePixelDataType texturePixelDataType = MG_Util::ConvertGLEnumToTexturePixelDataType(type);
bool isDepthFormat =
Bool isDepthFormat =
MG_Util::IsDepthFormatInternalFormat(MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat));
bool isStencilFormat =
Bool isStencilFormat =
MG_Util::IsStencilFormatInternalFormat(MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat));
if (!isDepthFormat) {
@@ -880,30 +907,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
});
FramebufferImpl::BackendFramebufferBindingProtector drawFboProtector(GL_DRAW_FRAMEBUFFER);
FramebufferImpl::BackendFramebufferBindingProtector readFboProtector(GL_READ_FRAMEBUFFER);
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
});
FramebufferImpl::BackendFramebufferBindingProtector::BindTempFBO(FramebufferTarget::Draw);
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
});
GLint currentTex;
MG_External::GLES::glGetIntegerv(Utils::GetBindingQuery(target, false), &currentTex);
GLint currentTex = backendTextureIt->second->GetBackendTextureId();
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
});
GLenum attachment = isStencilFormat ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
TempFBOBinder tempFBOBinder;
MG_External::GLES::glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, target, currentTex, level);
if (MG_External::GLES::glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
MGLOG_E("ES glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE");
// Protector will automatically revert to previous fbo states
return;
}
@@ -913,7 +928,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
});
// Protector will automatically revert to previous fbo states
}
}
@@ -938,10 +952,22 @@ namespace MobileGL::MG_Backend::DirectGLES {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
});
if (!UpdateTextureBindingAtTarget(target))
return;
if (!UpdateTextureBindingAtTarget(target)) return;
// Bind necessary FBO and texture
BindCurrentFBO(FramebufferTarget::Read);
Uint activeTextureUnit = MG_State::pGLContext->GetActiveTextureUnit();
const auto& textureObject = MG_State::pGLContext->GetTextureUnitObject(activeTextureUnit)
.GetBindingSlot(MG_Util::ConvertGLEnumToTextureTarget(target))
.GetBoundObject();
const auto& backendTextureIt = TextureImpl::g_backendTextureObjects.find(textureObject);
if (backendTextureIt == TextureImpl::g_backendTextureObjects.end()) {
MGLOG_E("CopyTexSubImage2D: No backend texture found for texture %u.",
textureObject ? textureObject->GetExternalIndex() : 0);
return;
}
backendTextureIt->second->Bind(target, activeTextureUnit);
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
});
@@ -950,10 +976,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
});
auto mglInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalFormat);
auto mgInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalFormat);
bool isDepthFormat = MG_Util::IsDepthFormatInternalFormat(mglInternalFormat);
bool isStencilFormat = MG_Util::IsStencilFormatInternalFormat(mglInternalFormat);
Bool isDepthFormat = MG_Util::IsDepthFormatInternalFormat(mgInternalFormat);
Bool isStencilFormat = MG_Util::IsStencilFormatInternalFormat(mgInternalFormat);
if (!isDepthFormat) {
MG_External::GLES::glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
@@ -962,29 +988,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
});
} else {
MGLOG_D("%s: Backend depth", __func__);
FramebufferImpl::BackendFramebufferBindingProtector drawFboProtector(GL_DRAW_FRAMEBUFFER);
FramebufferImpl::BackendFramebufferBindingProtector readFboProtector(GL_READ_FRAMEBUFFER);
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
});
FramebufferImpl::BackendFramebufferBindingProtector::BindTempFBO(FramebufferTarget::Draw);
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
});
GLint currentTex;
MG_External::GLES::glGetIntegerv(Utils::GetBindingQuery(target, false), &currentTex);
GLint currentTex = backendTextureIt->second->GetBackendTextureId();
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
});
GLenum attachment = isStencilFormat ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
TempFBOBinder tempFBOBinder;
MG_External::GLES::glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, target, currentTex, level);
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
});
if (MG_External::GLES::glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
MGLOG_E("ES glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE");
// Protector will automatically revert to previous fbo states
return;
}
@@ -994,7 +1009,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
});
// Protector will automatically revert to previous fbo states
}
}
@@ -1008,8 +1022,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
auto texture = slot.GetBoundObject();
auto backendTexture = TextureImpl::SyncTextureObjectToBackend(texture);
TextureImpl::BackendTextureBindingProtector protector(target);
backendTexture->Bind(target);
backendTexture->Bind(target, unitIndex);
MG_External::GLES::glGenerateMipmap(target);
}
@@ -1033,105 +1046,15 @@ namespace MobileGL::MG_Backend::DirectGLES {
RenderStateImpl::SyncRenderState();
BindCurrentFBO(FramebufferTarget::Draw);
auto backendFBOIt = FramebufferImpl::g_backendFramebufferObjects.find(
MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject());
if (backendFBOIt == FramebufferImpl::g_backendFramebufferObjects.end()) {
MGLOG_E("No backend FBO found for current draw FBO, cannot clear buffer.");
return;
}
auto backendFBO = backendFBOIt->second;
GLint realDrawbuffer = drawbuffer;
if (buffer == GL_COLOR) {
auto& stateDrawBuffers = backendFBOIt->first->GetDrawBuffers();
if (drawbuffer < 0 || drawbuffer >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
MGLOG_E("Invalid drawbuffer index: %d", drawbuffer);
return;
}
FramebufferAttachmentType attachmentType = stateDrawBuffers[drawbuffer];
if (attachmentType == FramebufferAttachmentType::None) {
MGLOG_D("Drawbuffer %d has no attachment, skipping clear", drawbuffer);
return;
}
bool found = false;
for (int i = 0; i < MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS; i++) {
if (backendFBO->GetCompactedAttachmentTypeAtDrawBufferIndex(i) == attachmentType) {
realDrawbuffer = i;
found = true;
break;
}
}
if (!found) {
MGLOG_E("Failed to find backend drawbuffer for attachment type: %d", static_cast<int>(attachmentType));
return;
}
} else if (buffer == GL_DEPTH || buffer == GL_STENCIL) {
if (drawbuffer != 0) {
MGLOG_W("Depth/stencil clear buffer index must be 0, got %d. Using 0.", drawbuffer);
}
realDrawbuffer = 0;
}
MG_External::GLES::glClearBufferfv(buffer, realDrawbuffer, value);
MG_External::GLES::glClearBufferfv(buffer, drawbuffer, value);
}
void ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value) {
TextureImpl::SyncNeccessaryTextures();
FramebufferImpl::SyncCurrentFBO();
RenderStateImpl::SyncRenderState();
BindCurrentFBO(FramebufferTarget::Draw);
auto backendFBOIt = FramebufferImpl::g_backendFramebufferObjects.find(
MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject());
if (backendFBOIt == FramebufferImpl::g_backendFramebufferObjects.end()) {
MGLOG_E("No backend FBO found for current draw FBO, cannot clear buffer.");
return;
}
auto backendFBO = backendFBOIt->second;
GLint realDrawbuffer = drawbuffer;
if (buffer == GL_COLOR) {
auto& stateDrawBuffers = backendFBOIt->first->GetDrawBuffers();
if (drawbuffer < 0 || drawbuffer >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
MGLOG_E("Invalid drawbuffer index: %d", drawbuffer);
return;
}
FramebufferAttachmentType attachmentType = stateDrawBuffers[drawbuffer];
if (attachmentType == FramebufferAttachmentType::None) {
MGLOG_D("Drawbuffer %d has no attachment, skipping clear", drawbuffer);
return;
}
bool found = false;
for (int i = 0; i < MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS; i++) {
if (backendFBO->GetCompactedAttachmentTypeAtDrawBufferIndex(i) == attachmentType) {
realDrawbuffer = i;
found = true;
break;
}
}
if (!found) {
MGLOG_E("Failed to find backend drawbuffer for attachment type: %d", static_cast<int>(attachmentType));
return;
}
} else if (buffer == GL_STENCIL) {
if (drawbuffer != 0) {
MGLOG_W("Stencil clear buffer index must be 0, got %d. Using 0.", drawbuffer);
}
realDrawbuffer = 0;
}
MG_External::GLES::glClearBufferiv(buffer, realDrawbuffer, value);
MG_External::GLES::glClearBufferiv(buffer, drawbuffer, value);
}
void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value) {
@@ -1140,51 +1063,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
RenderStateImpl::SyncRenderState();
BindCurrentFBO(FramebufferTarget::Draw);
auto backendFBOIt = FramebufferImpl::g_backendFramebufferObjects.find(
MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject());
if (backendFBOIt == FramebufferImpl::g_backendFramebufferObjects.end()) {
MGLOG_E("No backend FBO found for current draw FBO, cannot clear buffer.");
return;
}
auto backendFBO = backendFBOIt->second;
GLint realDrawbuffer = drawbuffer;
if (buffer == GL_COLOR) {
auto& stateDrawBuffers = backendFBOIt->first->GetDrawBuffers();
if (drawbuffer < 0 || drawbuffer >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
MGLOG_E("Invalid drawbuffer index: %d", drawbuffer);
return;
}
FramebufferAttachmentType attachmentType = stateDrawBuffers[drawbuffer];
if (attachmentType == FramebufferAttachmentType::None) {
MGLOG_D("Drawbuffer %d has no attachment, skipping clear", drawbuffer);
return;
}
bool found = false;
for (int i = 0; i < MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS; i++) {
if (backendFBO->GetCompactedAttachmentTypeAtDrawBufferIndex(i) == attachmentType) {
realDrawbuffer = i;
found = true;
break;
}
}
if (!found) {
MGLOG_E("Failed to find backend drawbuffer for attachment type: %d", static_cast<int>(attachmentType));
return;
}
} else {
MGLOG_E("ClearBufferuiv can only be used with GL_COLOR buffer, got %s",
MG_Util::ConvertGLEnumToString(buffer).c_str());
return;
}
MG_External::GLES::glClearBufferuiv(buffer, realDrawbuffer, value);
MG_External::GLES::glClearBufferuiv(buffer, drawbuffer, value);
}
} // namespace MobileGL::MG_Backend::DirectGLES
@@ -8,6 +8,8 @@
#pragma once
#include <Includes.h>
#include <MG_State/GLState/TextureState/TextureState.h>
#include <MG_State/GLState/SamplerState/SamplerObject.h>
#define CallAndCheck(operation) \
MGLOG_D("Call GLES func: %s", #operation); \
File diff suppressed because it is too large Load Diff
+42 -22
View File
@@ -16,25 +16,26 @@
namespace MobileGL::MG_Backend::DirectGLES {
namespace BufferImpl {
const GLenum TempBufferTarget = GL_ARRAY_BUFFER;
class BackendBufferObject {
public:
BackendBufferObject();
void SyncToBackend(SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject);
Uint GetBackendBufferId() { return m_backendBufferId; }
void Bind();
void Bind(GLenum target);
void Bind(GLenum target = TempBufferTarget);
private:
void SyncToBackend_glBufferData(SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject);
void SyncToBackend_glBufferSubData(SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject);
void SyncToBackend_glMapBufferRange(SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject,
Bool invalidate = true);
Bool invalidate = true, Bool unsynchronized = true);
Uint m_backendBufferId = 0;
SizeT m_prevBufferSize = 0;
Bool m_isInitialized = false;
};
extern BackendBufferObject* g_boundVertexBufferObject;
extern UnorderedMap<SharedPtr<MG_State::GLState::BufferObject>, SharedPtr<BackendBufferObject>>
g_backendBufferObjects;
} // namespace BufferImpl
@@ -43,13 +44,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
class BackendVertexArrayObject {
public:
BackendVertexArrayObject();
void SyncToBackend(SharedPtr<MG_State::GLState::VertexArrayObject>& stateVAOObject, Bool needDivisor);
void SyncToBackend(SharedPtr<MG_State::GLState::VertexArrayObject>& stateVAOObject);
Uint GetBackendVertexArrayId() { return m_backendVAOId; }
void Bind();
private:
void BindAttributeBuffer(Uint index, const MG_State::GLState::VertexAttribute& attrib);
Uint m_backendVAOId = 0;
Bool m_isInitialized = false;
Uint16 m_syncedIndexBufferVersion = 0;
Array<MG_State::GLState::VertexAttributeVersion, MG_State::GLState::VertexArrayObject::MAX_VERTEX_ATTRIBS>
m_syncedAttributeVersions;
};
extern UnorderedMap<SharedPtr<MG_State::GLState::VertexArrayObject>, SharedPtr<BackendVertexArrayObject>>
@@ -58,12 +64,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
namespace TextureImpl {
inline Bool IsSupportedTextureTarget(TextureTarget target) {
if (target == TextureTarget::Texture1D ||
target == TextureTarget::TextureRectangle ||
target == TextureTarget::Texture2DMultisampleArray ||
target == TextureTarget::Texture1DArray ||
target == TextureTarget::Texture2DMultisample ||
target == TextureTarget::Texture2DArray)
if (target == TextureTarget::Texture1D || target == TextureTarget::TextureRectangle ||
target == TextureTarget::Texture2DMultisampleArray || target == TextureTarget::Texture1DArray ||
target == TextureTarget::Texture2DMultisample || target == TextureTarget::Texture2DArray)
return false;
return true;
}
@@ -85,11 +88,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
bool operator!=(const StateTextureBasicInfo& other) const { return !(*this == other); }
};
inline const Uint TempTextureUnit = 0;
class BackendTextureObject {
public:
BackendTextureObject();
void SyncToBackend(SharedPtr<MG_State::GLState::ITextureObject>& stateTextureObject);
void Bind(GLenum target);
void SyncMipmapsToBackend(SharedPtr<MG_State::GLState::ITextureObject>& stateTextureObject);
void SyncBuiltinSamplerToBackend(SharedPtr<MG_State::GLState::ITextureObject>& stateTextureObject);
void SyncTextureParamsToBackend(SharedPtr<MG_State::GLState::ITextureObject>& stateTextureObject);
void Bind(GLenum target, Uint unit = TempTextureUnit);
Uint GetBackendTextureId();
private:
@@ -101,10 +107,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
FloatVec4 m_cacheBorderColor = {0.0f, 0.0f, 0.0f, 0.0f};
Vec4<TextureSwizzleParam> m_cacheSwizzleParams = {TextureSwizzleParam::Red, TextureSwizzleParam::Green,
TextureSwizzleParam::Blue, TextureSwizzleParam::Alpha};
Uint16 m_syncedSamplerVersion = 0;
Uint16 m_syncedTextureParamsVersion = 0;
};
void ActivateTextureUnit(Uint unit);
void UnbindTexture(Uint unit, GLenum target);
extern UnorderedMap<SharedPtr<MG_State::GLState::ITextureObject>, SharedPtr<BackendTextureObject>>
g_backendTextureObjects;
extern Array<Array<BackendTextureObject*, (SizeT)TextureTarget::TextureTargetCount>,
MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS>
g_boundTexturesCache;
extern Uint g_activeTextureUnit;
} // namespace TextureImpl
namespace FramebufferImpl {
@@ -115,7 +129,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
FramebufferTarget asTarget);
Uint GetBackendFramebufferId() { return m_backendFBOId; }
void Bind(FramebufferTarget target);
FramebufferAttachmentType GetCompactedAttachmentTypeAtDrawBufferIndex(Int index);
bool SyncAttachmentObject(GLenum glFBOTarget,
const MG_State::GLState::FramebufferAttachmentObject& attachmentObject,
GLenum glBackendAttachment);
// FramebufferAttachmentType GetCompactedAttachmentTypeAtDrawBufferIndex(Int index);
GLenum GetBackendAttachmentType(FramebufferAttachmentType frontendAtt) const;
private:
Uint m_backendFBOId = 0;
@@ -128,25 +146,22 @@ namespace MobileGL::MG_Backend::DirectGLES {
*/
FramebufferAttachmentType m_frontendDrawBuffers[MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS] = {
FramebufferAttachmentType::None};
/* this will save buffers in its compacted GL form,
not consecutive is not allowed
i.e. it could be like [COLOR_ATTACHMENT0, COLOR_ATTACHMENT5, COLOR_ATTACHMENT4]
(no GL_NONE among those)
*/
FramebufferAttachmentType
m_compactedFrontendDrawBuffers[MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS] = {
FramebufferAttachmentType::None};
/* this will save buffers in stricter ES rules
reversion, absence or not consecutive are not allowed, according to ES spec
i.e. it could be like [COLOR_ATTACHMENT0, COLOR_ATTACHMENT1, NONE, NONE, ...]
i.e. it could be like [COLOR_ATTACHMENT0, COLOR_ATTACHMENT1, NONE, COLOR_ATTACHMENT3, ...]
this array could be provided as data directly to ES `glDrawBuffers` function
*/
GLenum m_backendDrawBuffers[MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS] = {GL_NONE};
FramebufferAttachmentType m_frontendReadBuffer = FramebufferAttachmentType::Color0;
GLenum m_backendReadBuffer = GL_COLOR_ATTACHMENT0;
using FramebufferObject = MG_State::GLState::FramebufferObject;
FramebufferObject::FramebufferAttachmentVersionArray m_syncedFrontendAttachmentVersions = {0};
};
extern UnorderedMap<SharedPtr<MG_State::GLState::FramebufferObject>, SharedPtr<BackendFramebufferObject>>
g_backendFramebufferObjects;
extern Array<Uint16, SizeT(FramebufferTarget::FramebufferTargetCount)> g_fboBindVersions;
} // namespace FramebufferImpl
namespace PrgramImpl {
@@ -181,8 +196,13 @@ namespace MobileGL::MG_Backend::DirectGLES {
Uint m_backendSamplerId = 0;
Bool m_isInitialized = false;
SamplerParameters m_cacheSamplerParameters;
Uint16 m_syncedSamplerVersion = 0;
};
void UnbindSampler(Uint unit);
extern Array<BackendSamplerObject*, MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS>
g_boundSamplersCache;
extern UnorderedMap<SharedPtr<MG_State::GLState::SamplerObject>, SharedPtr<BackendSamplerObject>>
g_backendSamplerObjects;
} // namespace SamplerImpl
+7 -90
View File
@@ -19,108 +19,25 @@
#include <MG_Util/Converters/MGToGL/FramebufferEnumConverter.h>
namespace MobileGL::MG_Backend::DirectGLES {
namespace BufferImpl {
BackendBufferBindingProtector::BackendBufferBindingProtector(GLenum target) {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
m_target = target;
MG_External::GLES::glGetIntegerv(Utils::GetBindingQuery(target, false), &m_previousBinding);
}
namespace BufferImpl {} // namespace BufferImpl
BackendBufferBindingProtector::~BackendBufferBindingProtector() {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
MG_External::GLES::glBindBuffer(m_target, m_previousBinding);
}
} // namespace BufferImpl
namespace VertexArrayImpl {
BackendVertexArrayBindingProtector::BackendVertexArrayBindingProtector() {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
MG_External::GLES::glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &m_previousBinding);
}
BackendVertexArrayBindingProtector::~BackendVertexArrayBindingProtector() {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
MG_External::GLES::glBindVertexArray(m_previousBinding);
}
} // namespace VertexArrayImpl
namespace VertexArrayImpl {} // namespace VertexArrayImpl
namespace TextureImpl {
BackendTextureBindingProtector::BackendTextureBindingProtector(GLenum target) {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
m_target = target;
MG_External::GLES::glGetIntegerv(Utils::GetBindingQuery(target, true), &m_previousBinding);
}
BackendTextureBindingProtector::~BackendTextureBindingProtector() {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
MG_External::GLES::glBindTexture(m_target, m_previousBinding);
}
void GenerateTextureFormatInfo(TextureInternalFormat internalFormat, GLenum* outInternalFormat,
GLenum* outFormat, GLenum* outType) {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
using namespace MobileGL::MG_Util::TextureFormatProcessor;
auto options =
(MG_External::GLES::g_glesCaps.hasNorm16Texture) ? PixelFormatNormalizeOptionBit::None : PixelFormatNormalizeOptionBit::NoNorm16;
NormalizePixelFormat(
MG_Util::ConvertTextureInternalFormatToGLEnum(internalFormat),
options,
outInternalFormat,
outFormat, outType);
auto options = (MG_External::GLES::g_glesCaps.hasNorm16Texture) ? PixelFormatNormalizeOptionBit::None
: PixelFormatNormalizeOptionBit::NoNorm16;
NormalizePixelFormat(MG_Util::ConvertTextureInternalFormatToGLEnum(internalFormat), options,
outInternalFormat, outFormat, outType);
}
} // namespace TextureImpl
namespace FramebufferImpl {
BackendFramebufferBindingProtector::BackendFramebufferBindingProtector(GLenum target) {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
m_target = target;
MG_External::GLES::glGetIntegerv(Utils::GetBindingQuery(target, false), &m_previousBinding);
}
BackendFramebufferBindingProtector::~BackendFramebufferBindingProtector() {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
MG_External::GLES::glBindFramebuffer(m_target, m_previousBinding);
}
GLuint BackendFramebufferBindingProtector::GetTempFBO(FramebufferTarget target) {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
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) {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
GLuint fbo = GetTempFBO(target);
GLenum glTarget = MG_Util::ConvertFramebufferTargetToGLEnum(target);
MG_External::GLES::glBindFramebuffer(glTarget, fbo);
}
} // namespace FramebufferImpl
namespace FramebufferImpl {} // namespace FramebufferImpl
namespace PrgramImpl {
String ProcessOutColorLocations(const String& glslCode) {
+2 -50
View File
@@ -27,66 +27,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
};
} // namespace DebugImpl
namespace BufferImpl {
class BackendBufferBindingProtector {
public:
BackendBufferBindingProtector(GLenum target);
~BackendBufferBindingProtector();
private:
GLenum m_target;
GLint m_previousBinding = 0;
};
} // namespace BufferImpl
namespace BufferImpl {} // namespace BufferImpl
namespace VertexArrayImpl {
GLenum GetBindingQuery(GLenum target, bool isTexture);
class BackendVertexArrayBindingProtector {
public:
BackendVertexArrayBindingProtector();
~BackendVertexArrayBindingProtector();
private:
GLint m_previousBinding = 0;
};
} // namespace VertexArrayImpl
namespace TextureImpl {
class BackendTextureBindingProtector {
public:
BackendTextureBindingProtector(GLenum target);
~BackendTextureBindingProtector();
private:
GLenum m_target;
GLint m_previousBinding = 0;
};
void GenerateTextureFormatInfo(TextureInternalFormat internalFormat, GLenum* outInternalFormat,
GLenum* outFormat, GLenum* outType);
} // namespace TextureImpl
namespace FramebufferImpl {
class BackendFramebufferBindingProtector {
public:
BackendFramebufferBindingProtector(GLenum target);
~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
namespace FramebufferImpl {} // namespace FramebufferImpl
namespace PrgramImpl {
String ProcessOutColorLocations(const String& glslCode);
@@ -88,7 +88,7 @@ namespace MobileGL {
return MG_External::EGL::eglQuerySurface(display, surface, attribute, value);
}
char const * QueryString(EGLDisplay display, EGLint name) {
char const* QueryString(EGLDisplay display, EGLint name) {
return MG_External::EGL::eglQueryString(display, name);
}
@@ -122,7 +122,7 @@ namespace MobileGL {
}
EGLSurface CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap,
const EGLint* attrib_list) {
const EGLint* attrib_list) {
return MG_External::EGL::eglCreatePixmapSurface(dpy, config, pixmap, attrib_list);
}
@@ -170,51 +170,45 @@ namespace MobileGL {
return (__eglMustCastToProperFunctionPointerType)proc;
}
EGLSync CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib * attrib_list) {
EGLSync CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib* attrib_list) {
return MG_External::EGL::eglCreateSync(dpy, type, attrib_list);
}
EGLBoolean DestroySync(EGLDisplay dpy, EGLSync sync) {
return MG_External::EGL::eglDestroySync(dpy, sync);
}
EGLint ClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout) {
return MG_External::EGL::eglClientWaitSync(dpy, sync, flags, timeout);
}
EGLBoolean GetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib * value) {
EGLBoolean GetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib* value) {
return MG_External::EGL::eglGetSyncAttrib(dpy, sync, attribute, value);
}
EGLImage CreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib * attrib_list) {
EGLImage CreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer,
const EGLAttrib* attrib_list) {
return MG_External::EGL::eglCreateImage(dpy, ctx, target, buffer, attrib_list);
}
EGLBoolean DestroyImage(EGLDisplay dpy, EGLImage image) {
return MG_External::EGL::eglDestroyImage(dpy, image);
}
EGLDisplay GetPlatformDisplay(EGLenum platform, void * native_display, const EGLAttrib * attrib_list) {
EGLDisplay GetPlatformDisplay(EGLenum platform, void* native_display, const EGLAttrib* attrib_list) {
return MG_External::EGL::eglGetPlatformDisplay(platform, native_display, attrib_list);
}
EGLSurface CreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void * native_window, const EGLAttrib * attrib_list) {
EGLSurface CreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void* native_window,
const EGLAttrib* attrib_list) {
return MG_External::EGL::eglCreatePlatformWindowSurface(dpy, config, native_window, attrib_list);
}
EGLSurface CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void * native_pixmap, const EGLAttrib * attrib_list) {
EGLSurface CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void* native_pixmap,
const EGLAttrib* attrib_list) {
return MG_External::EGL::eglCreatePlatformPixmapSurface(dpy, config, native_pixmap, attrib_list);
}
EGLBoolean WaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags) {
return MG_External::EGL::eglWaitSync(dpy, sync, flags);
}
@@ -98,7 +98,7 @@ namespace MobileGL {
return EGL_TRUE;
}
char const * QueryString(EGLDisplay display, EGLint name) {
char const* QueryString(EGLDisplay display, EGLint name) {
return "";
}
@@ -132,7 +132,7 @@ namespace MobileGL {
}
EGLSurface CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap,
const EGLint* attrib_list) {
const EGLint* attrib_list) {
return (EGLSurface)1;
}
@@ -29,7 +29,7 @@ namespace MobileGL {
EGLBoolean BindAPI(EGLenum api);
EGLSurface GetCurrentSurface(EGLint readdraw);
EGLBoolean QuerySurface(EGLDisplay display, EGLSurface surface, EGLint attribute, EGLint* value);
char const * QueryString(EGLDisplay display, EGLint name);
char const* QueryString(EGLDisplay display, EGLint name);
EGLBoolean SwapInterval(EGLDisplay dpy, EGLint interval);
EGLBoolean SwapBuffers(EGLDisplay dpy, EGLSurface draw);
EGLSurface CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint* attrib_list);
@@ -39,7 +39,7 @@ namespace MobileGL {
EGLSurface CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
EGLConfig config, const EGLint* attrib_list);
EGLSurface CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap,
const EGLint* attrib_list);
const EGLint* attrib_list);
EGLBoolean GetConfigs(EGLDisplay dpy, EGLConfig* configs, EGLint config_size, EGLint* num_config);
EGLDisplay GetCurrentDisplay(void);
EGLenum QueryAPI(void);
@@ -49,15 +49,18 @@ namespace MobileGL {
EGLBoolean WaitGL(void);
EGLBoolean WaitNative(EGLint engine);
__eglMustCastToProperFunctionPointerType GetProcAddress(const char* name);
EGLSync CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib * attrib_list);
EGLSync CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib* attrib_list);
EGLBoolean DestroySync(EGLDisplay dpy, EGLSync sync);
EGLint ClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout);
EGLBoolean GetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib * value);
EGLImage CreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib * attrib_list);
EGLBoolean GetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib* value);
EGLImage CreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer,
const EGLAttrib* attrib_list);
EGLBoolean DestroyImage(EGLDisplay dpy, EGLImage image);
EGLDisplay GetPlatformDisplay(EGLenum platform, void * native_display, const EGLAttrib * attrib_list);
EGLSurface CreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void * native_window, const EGLAttrib * attrib_list);
EGLSurface CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void * native_pixmap, const EGLAttrib * attrib_list);
EGLDisplay GetPlatformDisplay(EGLenum platform, void* native_display, const EGLAttrib* attrib_list);
EGLSurface CreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void* native_window,
const EGLAttrib* attrib_list);
EGLSurface CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void* native_pixmap,
const EGLAttrib* attrib_list);
EGLBoolean WaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags);
} // namespace MG_Impl::EGLImpl
} // namespace MobileGL
+2 -2
View File
@@ -525,8 +525,7 @@ namespace MobileGL {
auto& point = MG_State::pGLContext->GetBufferBindingPoint(bufferTarget, pointIndex);
point.Bind(bufferObject);
point.SetRange(Range1D(0, bufferObject->GetSize()));
MGLOG_D("%s: set range (0, %d)", __func__,
bufferObject->GetSize());
MGLOG_D("%s: set range (0, %d)", __func__, bufferObject->GetSize());
}
void BindBufferRange_State(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) {
@@ -575,6 +574,7 @@ namespace MobileGL {
return MapBuffer_State(target, access);
}
// FIXME: this should be a "backend" function
void CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset,
GLsizeiptr size) {
CopyBufferSubData_State(readTarget, writeTarget, readOffset, writeOffset, size);
+12 -6
View File
@@ -12,16 +12,22 @@
namespace MobileGL {
namespace MG_Impl::GLImpl {
/* @INSERTION_POINT:FUNCTION_DECLARATION@ */
void MultiDrawElementsIndirect(GLenum mode, GLenum type, const void* indirect, GLsizei drawcount, GLsizei stride);
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, const void* indices, GLint basevertex);
void DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type,
const void* indices, GLint basevertex);
void DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices);
void DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance);
void DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instancecount, GLint basevertex);
void DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instancecount, GLuint baseinstance);
void DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices,
GLsizei instancecount, GLint basevertex, GLuint baseinstance);
void DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type, const void* indices,
GLsizei instancecount, GLint basevertex);
void DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices,
GLsizei instancecount, GLuint baseinstance);
void DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instancecount);
void DrawElementsIndirect(GLenum mode, GLenum type, const void* indirect);
void DrawArraysInstancedBaseInstance(GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance);
void DrawArraysInstancedBaseInstance(GLenum mode, GLint first, GLsizei count, GLsizei instancecount,
GLuint baseinstance);
void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
void DrawArraysIndirect(GLenum mode, const void* indirect);
void DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const void* indices, GLint basevertex);
@@ -304,6 +304,25 @@ namespace MobileGL {
}
}
void ReadBuffer_State(GLenum mode) {
auto attType = MG_Util::ConvertGLEnumToFramebufferAttachmentType(mode);
// ------------------- Check validity begin ------------------------
if (attType == FramebufferAttachmentType::Unknown) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
std::format("`mode` = {} is not an accepted value.",
MG_Util::ConvertGLEnumToString(mode))));
return;
}
// Get bound framebuffer
auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Read);
auto fbo = bindingSlot.GetBoundObject();
fbo->SetReadBuffer(attType);
}
void DeleteRenderbuffers_State(GLsizei n, const GLuint* renderbuffers) {
if (n < 0) {
MG_State::pGLContext->RecordError(
@@ -575,6 +594,10 @@ namespace MobileGL {
DrawBuffers_State(n, bufs);
}
void ReadBuffer(GLenum src) {
ReadBuffer_State(src);
}
void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) {
DeleteRenderbuffers_State(n, renderbuffers);
}
@@ -46,6 +46,7 @@ namespace MobileGL {
void FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
void DrawBuffer(GLenum buf);
void DrawBuffers(GLsizei n, const GLenum* bufs);
void ReadBuffer(GLenum src);
void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers);
void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers);
GLenum CheckFramebufferStatus(GLenum target);
+2 -2
View File
@@ -567,7 +567,7 @@ namespace MobileGL {
*params = MG_State::pGLContext->GetPixelStoreParam(PixelStoreParam::PackImageHeight);
break;
case GL_PACK_LSB_FIRST:
*params = MG_State::pGLContext->GetPixelStoreParam(PixelStoreParam::PackLsbFirst);
*params = MG_State::pGLContext->GetPixelStoreParam(PixelStoreParam::PackLSBFirst);
break;
case GL_PACK_ROW_LENGTH:
*params = MG_State::pGLContext->GetPixelStoreParam(PixelStoreParam::PackRowLength);
@@ -839,7 +839,7 @@ namespace MobileGL {
*params = MG_State::pGLContext->GetPixelStoreParam(PixelStoreParam::UnpackImageHeight);
break;
case GL_UNPACK_LSB_FIRST:
*params = MG_State::pGLContext->GetPixelStoreParam(PixelStoreParam::UnpackLsbFirst);
*params = MG_State::pGLContext->GetPixelStoreParam(PixelStoreParam::UnpackLSBFirst);
break;
case GL_UNPACK_ROW_LENGTH:
*params = MG_State::pGLContext->GetPixelStoreParam(PixelStoreParam::UnpackRowLength);
@@ -516,15 +516,15 @@ namespace MobileGL {
void Uniform_State(MG_State::GLState::ProgramObject& programObject, GLuint location, T* value,
SizeT byteOffsetInsideUniform = 0) {
if (!programObject.IsUniformOpaqueAtLocation(location)) {
MGLOG_D("%s: program = %d, location = %d, maxLocation = %d", __func__,
programObject.GetExternalIndex(), location, programObject.GetMaxUniformLocation());
MGLOG_D("%s: program = %d, location = %d, maxLocation = %d", __func__, programObject.GetExternalIndex(),
location, programObject.GetMaxUniformLocation());
auto size = programObject.GetUniformSizesInBytes(location);
auto offset = programObject.GetUniformOffset(location);
MOBILEGL_ASSERT(size >= ItemCount * sizeof(T),
"Uniform size mismatch, expected at least %zu bytes, got %zu bytes.",
ItemCount * sizeof(T), size);
MGLOG_D("%s: program = %d, location = %d, byteOffset = %d", __func__,
programObject.GetExternalIndex(), location, offset + byteOffsetInsideUniform);
MGLOG_D("%s: program = %d, location = %d, byteOffset = %d", __func__, programObject.GetExternalIndex(),
location, offset + byteOffsetInsideUniform);
Memcpy((char*)programObject.MapUBO() + offset + byteOffsetInsideUniform, value, ItemCount * sizeof(T));
} else {
auto* ttype = programObject.GetUniformTType(location);
@@ -241,10 +241,6 @@ namespace MobileGL {
// TODO: implement
}
void ReadBuffer_State(GLenum src) {
// TODO: implement
}
void ClearStencil_State(GLint s) {
// TODO: implement
}
@@ -390,10 +386,6 @@ namespace MobileGL {
BlendColor_State(red, green, blue, alpha);
}
void ReadBuffer(GLenum src) {
ReadBuffer_State(src);
}
void ClearStencil(GLint s) {
ClearStencil_State(s);
}
@@ -45,7 +45,6 @@ namespace MobileGL {
void BlendFuncSeparate(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
void BlendEquation(GLenum mode);
void BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
void ReadBuffer(GLenum src);
void ClearStencil(GLint s);
void ClearDepth(GLclampd depth);
void ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+83 -36
View File
@@ -7,26 +7,27 @@
// End of Source File Header
#include "GL_Texture.h"
#include "GL/gl.h"
#include "Config.h"
#if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES
#include <MG_Backend/DirectGLES/DirectGLES.h>
#endif
#include "MG_Util/Types.h"
#include "Validators.h"
#include "ProxyTexture.h"
#include "MG_State/GLState/TextureState/TextureObjectBuffer.h"
#include "MG_Util/Converters/GLToStr/GLEnumConverter.h"
#include "MG_Util/Texture/TextureFormatProcessor.h"
#include <MG_State/GLState/Core.h>
#include <MG_Util/Metrics/TextureMetrics.h>
#include <MG_State/GLState/ErrorState/Error.h>
#include <MG_Util/Texture/PixelStoreProcessor.h>
#include <MG_Util/Texture/TextureFormatProcessor.h>
#include <MG_Util/Classifiers/TextureEnumClassifier.h>
#include <MG_Util/Converters/GLToStr/GLEnumConverter.h>
#include <MG_Util/Converters/MGToMG/TextureEnumConverter.h>
#include <MG_Util/Converters/GLToMG/TextureEnumConverter.h>
#include <MG_Util/Converters/MGToGL/TextureEnumConverter.h>
#include <MG_Util/Converters/MGToStr/TextureEnumConverter.h>
#include <MG_State/GLState/TextureState/TextureObjectBuffer.h>
#if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES
#include <MG_Backend/DirectGLES/DirectGLES.h>
#endif
namespace MobileGL {
namespace MG_Impl::GLImpl {
@@ -63,8 +64,7 @@ namespace MobileGL {
// TextureInternalFormat textureInternalFormat =
// MG_Util::ConvertGLEnumToTextureInternalFormat(format);
MGLOG_D("TexSubImage2D_State: target = %s, level = %d, (%d, %d), format = %s, pixels = %p",
MG_Util::ConvertGLEnumToString(target).c_str(), level,
width, height,
MG_Util::ConvertGLEnumToString(target).c_str(), level, width, height,
MG_Util::ConvertTextureInputFormatToString(textureInputFormat).c_str(), pixels);
// ===================== Error Checking ==============================
if (!TextureImpl::ValidateTexturePixelDataType(texturePixelDataType)) return;
@@ -502,14 +502,18 @@ namespace MobileGL {
GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels) {
MGLOG_D(
"%s called with target: %s, level: %d, internalformat: %s, width: %d, height: %d, depth: %d, "
"border: %d, format: %s, type: %s (%u), pixels: %p", __func__,
MG_Util::ConvertTextureUploadTargetToString(MG_Util::ConvertGLEnumToTextureUploadTarget(target)).c_str(),
"border: %d, format: %s, type: %s (%u), pixels: %p",
__func__,
MG_Util::ConvertTextureUploadTargetToString(MG_Util::ConvertGLEnumToTextureUploadTarget(target))
.c_str(),
level,
MG_Util::ConvertTextureInternalFormatToString(
MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat)).c_str(),
MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat))
.c_str(),
width, height, depth, border,
MG_Util::ConvertTextureInputFormatToString(MG_Util::ConvertGLEnumToTextureInputFormat(format)).c_str(),
MG_Util::ConvertTexturePixelDataTypeToString(MG_Util::ConvertGLEnumToTexturePixelDataType(type)).c_str(),
MG_Util::ConvertTexturePixelDataTypeToString(MG_Util::ConvertGLEnumToTexturePixelDataType(type))
.c_str(),
type, pixels);
// ======================= Converting ================================
TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
@@ -580,13 +584,13 @@ namespace MobileGL {
reinterpret_cast<SizeT>(pixels);
}
MOBILEGL_ASSERT(nullptr != dynamic_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get()),
"Texture object here should always be an object with mipmap");
auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
// Allocate in TextureObject
textureMipmapObject->AllocateStorage(textureUploadingTarget, level, {{width, height, depth}, internalBytes});
textureMipmapObject->AllocateStorage(textureUploadingTarget, level,
{{width, height, depth}, internalBytes});
if (!originalPixels) {
MGLOG_D("%s: No input pixel and no PBO bound, no pixel transfer", __func__);
@@ -601,8 +605,8 @@ namespace MobileGL {
if (processedPixels && imageSize > 0) {
if (imageSize != internalBytes) {
MGLOG_W("%s: Processed pixel data size (%zu) does not match expected size (%zu). "
"This may indicate an alignment or processing issue.", __func__,
imageSize, internalBytes);
"This may indicate an alignment or processing issue.",
__func__, imageSize, internalBytes);
}
const SizeT copySize = std::min(imageSize, internalBytes);
@@ -623,20 +627,16 @@ namespace MobileGL {
TextureInputFormat textureInputFormat = MG_Util::ConvertGLEnumToTextureInputFormat(format);
TexturePixelDataType texturePixelDataType = MG_Util::ConvertGLEnumToTexturePixelDataType(type);
TextureInternalFormat textureInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat);
MGLOG_D(
"%s called with target: %s (%s), level: %d, internalformat: %s (%s), width: %d, height: %d, "
"border: %d, format: %s (%s), type: %s (%s), pixels: %p", __func__,
MG_Util::ConvertTextureUploadTargetToString(textureUploadingTarget).c_str(),
MG_Util::ConvertGLEnumToString(target).c_str(),
level,
MGLOG_D("%s called with target: %s (%s), level: %d, internalformat: %s (%s), width: %d, height: %d, "
"border: %d, format: %s (%s), type: %s (%s), pixels: %p",
__func__, MG_Util::ConvertTextureUploadTargetToString(textureUploadingTarget).c_str(),
MG_Util::ConvertGLEnumToString(target).c_str(), level,
MG_Util::ConvertTextureInternalFormatToString(textureInternalFormat).c_str(),
MG_Util::ConvertGLEnumToString(internalformat).c_str(),
width, height, border,
MG_Util::ConvertGLEnumToString(internalformat).c_str(), width, height, border,
MG_Util::ConvertTextureInputFormatToString(textureInputFormat).c_str(),
MG_Util::ConvertGLEnumToString(format).c_str(),
MG_Util::ConvertTexturePixelDataTypeToString(texturePixelDataType).c_str(),
MG_Util::ConvertGLEnumToString(type).c_str(),
pixels);
MG_Util::ConvertGLEnumToString(type).c_str(), pixels);
// ===================== Error Checking ==============================
if (!TextureImpl::ValidateTexturePixelDataType(texturePixelDataType)) return;
if (!TextureImpl::ValidateTextureInputFormat(textureInputFormat)) return;
@@ -661,7 +661,8 @@ namespace MobileGL {
// indicated by type.
// ======================= Processing ================================
textureInternalFormat = MG_Util::ConvertInternalFormatToSized(textureInternalFormat, textureInputFormat, texturePixelDataType);
textureInternalFormat =
MG_Util::ConvertInternalFormatToSized(textureInternalFormat, textureInputFormat, texturePixelDataType);
SharedPtr<MG_State::GLState::ITextureObject> textureObject = nullptr;
Bool isProxy = TextureImpl::IsProxyTextureTarget(textureUploadingTarget);
if (isProxy) {
@@ -714,9 +715,6 @@ namespace MobileGL {
MGLOG_D("%s: Allocating %d bytes at mip %d", __func__, internalBytes, level);
textureMipmapObject->AllocateStorage(textureUploadingTarget, level, {{width, height, 1}, internalBytes});
MGLOG_D("%s: mark mip %d as dirty", __func__, level);
textureMipmapObject->MarkStorageDirty(textureUploadingTarget, level, true);
if (!originalPixels) {
MGLOG_D("%s: No input pixel and no PBO bound, no pixel transfer", __func__);
return;
@@ -740,6 +738,9 @@ namespace MobileGL {
}
free(processedPixels);
MGLOG_D("%s: mark mip %d as dirty", __func__, level);
textureMipmapObject->MarkStorageDirty(textureUploadingTarget, level, true);
}
void TexImage1D_State(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLint border,
@@ -1227,12 +1228,58 @@ namespace MobileGL {
}
void CopyTexImage2D_State(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width,
GLsizei height, GLint border) {
GLenum outInternalFormat, format, type;
MG_Util::TextureFormatProcessor::NormalizePixelFormat(internalformat, 0, &outInternalFormat, &format, &type);
GLsizei height, GLint border) {
auto internalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat);
const auto& currentReadFBO =
MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject();
if (!currentReadFBO) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>(
"MG_Impl/GLImpl", "CopyTexImage2D_State",
"No framebuffer is currently bound to the GL_READ_FRAMEBUFFER target."));
return;
}
Bool isDepth = MG_Util::IsDepthFormatInternalFormat(internalFormat);
Bool isStencil = MG_Util::IsStencilFormatInternalFormat(internalFormat);
TextureInternalFormat srcInternalFormat = TextureInternalFormat::Unknown;
#define GET_SRC_INTERNAL_FORMAT(AttachmentType) \
const auto& srcAttachment = currentReadFBO->GetAttachment(AttachmentType); \
if (srcAttachment.IsTexture()) { \
const auto& texObj = srcAttachment.GetTexture(); \
srcInternalFormat = texObj->GetFormat(); \
} else if (srcAttachment.IsRenderbuffer()) { \
const auto& rboObj = srcAttachment.GetRenderbuffer(); \
srcInternalFormat = rboObj->GetInternalFormat(); \
} else { \
MG_State::pGLContext->RecordError( \
ErrorCode::InvalidOperation, \
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "CopyTexImage2D_State", \
"The attachment specified by the read buffer is incomplete.")); \
return; \
}
if (isDepth) {
GET_SRC_INTERNAL_FORMAT(FramebufferAttachmentType::Depth);
} else if (isStencil) {
GET_SRC_INTERNAL_FORMAT(FramebufferAttachmentType::Stencil);
} else {
const auto& readBufferType = currentReadFBO->GetReadBuffer();
GET_SRC_INTERNAL_FORMAT(readBufferType);
}
if (!TextureImpl::ValidateBaseInternalFormatMatch(internalFormat, srcInternalFormat))
THROW_UNIMPL_EXCEPTION;
GLenum outInternalFormat = MG_Util::ConvertTextureInternalFormatToGLEnum(srcInternalFormat);
GLenum realInternalFormat = GL_RGBA8;
GLenum format = GL_DEPTH_COMPONENT;
GLenum type = GL_UNSIGNED_INT;
MG_Util::TextureFormatProcessor::NormalizePixelFormat(
outInternalFormat, PixelFormatNormalizeOptionBit::None, &realInternalFormat, &format, &type);
const auto pixelUnpackBufferObject =
MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelUnpack).GetBoundObject();
TexImage2D_State(target, level, outInternalFormat, width, height, border, format, type, nullptr);
MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelUnpack).GetBoundObject();
TexImage2D_State(target, level, realInternalFormat, width, height, border, format, type, nullptr);
MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelUnpack).Bind(pixelUnpackBufferObject);
}
+4 -4
View File
@@ -20,10 +20,10 @@ namespace MobileGL {
const GLvoid* pixels);
void TexParameterf(GLenum target, GLenum pname, GLfloat param);
void TexParameteri(GLenum target, GLenum pname, GLint param);
void TexParameterfv(GLenum target, GLenum pname, const GLfloat * params);
void TexParameteriv(GLenum target, GLenum pname, const GLint * params);
void TexParameterIiv(GLenum target, GLenum pname, const GLint * params);
void TexParameterIuiv(GLenum target, GLenum pname, const GLuint * params);
void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
void TexParameteriv(GLenum target, GLenum pname, const GLint* params);
void TexParameterIiv(GLenum target, GLenum pname, const GLint* params);
void TexParameterIuiv(GLenum target, GLenum pname, const GLuint* params);
void TexImage3DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height,
GLsizei depth, GLboolean fixedsamplelocations);
+27 -7
View File
@@ -7,13 +7,12 @@
// End of Source File Header
#include "Validators.h"
#include "MG_State/GLState/TextureState/TextureObject.h"
#include "MG_Util/Types.h"
#include <MG_State/GLState/Core.h>
#include <MG_State/GLState/ErrorState/Error.h>
#include <MG_Util/Converters/GLToStr/GLEnumConverter.h>
#include <MG_Util/Converters/GLToMG/TextureEnumConverter.h>
#include <MG_Util/Converters/MGToGL/TextureEnumConverter.h>
#include <MG_Util/Converters/MGToMG/TextureEnumConverter.h>
#include <MG_Util/Converters/MGToStr/TextureEnumConverter.h>
namespace MobileGL::MG_Impl::GLImpl {
@@ -170,7 +169,9 @@ namespace MobileGL::MG_Impl::GLImpl {
}
return true;
}
Bool ValidateTextureInternalFormatCompatibleWithInput(TextureInputFormat format, TextureInternalFormat internalFormat,
Bool ValidateTextureInternalFormatCompatibleWithInput(TextureInputFormat format,
TextureInternalFormat internalFormat,
TexturePixelDataType type) {
if (type == TexturePixelDataType::UnsignedByte332 || type == TexturePixelDataType::UnsignedByte233Rev ||
type == TexturePixelDataType::UnsignedShort565 || type == TexturePixelDataType::UnsignedShort565Rev ||
@@ -178,7 +179,8 @@ namespace MobileGL::MG_Impl::GLImpl {
if (format != TextureInputFormat::RGB) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureInternalFormatCompatibleWithInput",
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl",
"ValidateTextureInternalFormatCompatibleWithInput",
"Invalid format for the given type"));
return false;
}
@@ -193,7 +195,8 @@ namespace MobileGL::MG_Impl::GLImpl {
if (format != TextureInputFormat::RGBA && format != TextureInputFormat::BGRA) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureInternalFormatCompatibleWithInput",
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl",
"ValidateTextureInternalFormatCompatibleWithInput",
"Invalid format for the given type"));
return false;
}
@@ -206,7 +209,8 @@ namespace MobileGL::MG_Impl::GLImpl {
if (format != TextureInputFormat::DepthComponent) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureInternalFormatCompatibleWithInput",
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl",
"ValidateTextureInternalFormatCompatibleWithInput",
"Invalid format for depth component internal format"));
return false;
}
@@ -299,5 +303,21 @@ namespace MobileGL::MG_Impl::GLImpl {
}
return true;
}
Bool ValidateBaseInternalFormatMatch(TextureInternalFormat format1, TextureInternalFormat format2) {
auto unsizedFormat1 = MG_Util::ConvertInternalFormatToUnsized(format1);
auto unsizedFormat2 = MG_Util::ConvertInternalFormatToUnsized(format2);
if (unsizedFormat1 != unsizedFormat2) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>(
std::format("MG_Impl/GLImpl", "ValidateBaseInternalFormatMatch",
"The base internal format of the two formats do not match ({} vs. {})",
MG_Util::ConvertTextureInternalFormatToString(unsizedFormat1).c_str(),
MG_Util::ConvertTextureInternalFormatToString(unsizedFormat2).c_str())));
return false;
}
return true;
} // namespace TextureImpl
} // namespace TextureImpl
} // namespace MobileGL::MG_Impl::GLImpl
} // namespace MobileGL::MG_Impl::GLImpl
+4 -1
View File
@@ -7,6 +7,7 @@
// End of Source File Header
#pragma once
#include "MG_State/GLState/TextureState/TextureEnum.h"
#include "MG_Util/Types.h"
#include <Includes.h>
#include <MG_State/GLState/TextureState/TextureObject.h>
@@ -23,7 +24,8 @@ namespace MobileGL::MG_Impl::GLImpl {
Bool ValidateTextureSizeRange(SizeT width, SizeT height, SizeT depth);
Bool ValidateTextureInternalFormat(TextureInternalFormat format);
Bool ValidateTextureBorderNumber(Int border);
Bool ValidateTextureInternalFormatCompatibleWithInput(TextureInputFormat format, TextureInternalFormat internalFormat,
Bool ValidateTextureInternalFormatCompatibleWithInput(TextureInputFormat format,
TextureInternalFormat internalFormat,
TexturePixelDataType type);
Bool ValidateTextureLevelWithUploadTarget(TextureUploadTarget target, Int level);
Bool ValidateTextureObject(SharedPtr<MG_State::GLState::ITextureObject> textureObject);
@@ -31,5 +33,6 @@ namespace MobileGL::MG_Impl::GLImpl {
TextureTarget target);
Bool ValidateTextureSubImageOffsets(SharedPtr<MG_State::GLState::ITextureObject> textureObject, Int xoffset,
Int width, Int yoffset = 0, Int height = 0, Int zoffset = 0, Int depth = 0);
Bool ValidateBaseInternalFormatMatch(TextureInternalFormat format1, TextureInternalFormat format2);
} // namespace TextureImpl
} // namespace MobileGL::MG_Impl::GLImpl
+3 -3
View File
@@ -7,9 +7,9 @@
// End of Source File Header
#include "GetProcAddress.h"
#define GETPROC(name, var) \
if (strcmp(#name, var) == 0) { \
return (void*)name; \
#define GETPROC(name, var) \
if (strcmp(#name, var) == 0) { \
return (void*)name; \
}
namespace MobileGL {
@@ -14,14 +14,18 @@ namespace MobileGL {
namespace GLState {
BufferObject::BufferObject(Uint externalIndex)
: m_externalIndex(externalIndex), m_size(0), m_usage(BufferUsage::StaticDraw), m_isMapped(false),
m_mappingAccess(BufferMappingAccessBit::Null), m_dirtyRange({0, 0}), m_mappedRange({0, 0}),
m_dataPtr(MakeShared<Data>()) {}
m_mappingAccess(BufferMappingAccessBit::Null),
m_change(BufferChangeBits::DirtyBit | BufferChangeBits::PreferReallocationBit), m_mappedRange({0, 0}),
m_dataPtr(MakeShared<Data>()) {
m_change.DirtyRanges.reserve(BufferChange::DEFAULT_RESERVED_DIRTY_RANGES_COUNT);
}
void BufferObject::Resize(SizeT size) {
m_size = size;
m_dataPtr->reserve(std::bit_ceil(size)); // power-of-2 reserve
m_dataPtr->resize(size);
m_dirtyRange = {0, 0};
m_change.Bits |= BufferChangeBits::DirtyBit;
m_change.Bits |= BufferChangeBits::PreferReallocationBit;
}
void BufferObject::UploadData(DataPtr data, SizeT atOffset) {
@@ -30,7 +34,14 @@ namespace MobileGL {
data.size, m_size);
MOBILEGL_ASSERT(!m_isMapped, "Cannot upload data while buffer is mapped.");
Memcpy(m_dataPtr->data() + atOffset, data.data, data.size);
m_dirtyRange.UnionUpdate(atOffset, atOffset + data.size);
m_change.DirtyRanges.Add({atOffset, atOffset + data.size});
m_change.Bits |= BufferChangeBits::DirtyBit;
m_change.Bits |= BufferChangeBits::ForbidInvalidationBit;
m_change.Bits |= BufferChangeBits::ForbidUnsynchronizationBit;
// This function may be called by `glBufferData`, but we still set the forbid bits above,
// because when `PreferReallocationBit` is set, those bits are ignored anyway.
// The bits can fit the `glBufferSubData` semantics
// (though `glBufferSubData` calls `UploadSubData` instead).
}
void BufferObject::SetUsage(BufferUsage usage) {
@@ -44,7 +55,8 @@ namespace MobileGL {
if (!(m_mappingAccess & BufferMappingAccessBit::FlushExplicit)) { // if we didn't flush explicitly
Memcpy(m_dataPtr->data() + m_mappedRange.start, m_stagingData.data(),
m_mappedRange.end - m_mappedRange.start);
m_dirtyRange.UnionUpdate(m_mappedRange.start, m_mappedRange.end);
m_change.DirtyRanges.Add({m_mappedRange.start, m_mappedRange.end});
m_change.Bits |= BufferChangeBits::DirtyBit;
}
m_stagingData.clear();
@@ -69,7 +81,8 @@ namespace MobileGL {
"Flush range out of bounds: mappedRange.end (%zu) < end (%zu)", m_mappedRange.end, end);
Memcpy(m_dataPtr->data() + start, m_stagingData.data() + offset, length);
m_dirtyRange.UnionUpdate(start, end);
m_change.DirtyRanges.Add({start, end});
m_change.Bits |= BufferChangeBits::DirtyBit;
}
void BufferObject::UploadSubData(DataPtr data, SizeT atOffset) {
@@ -79,7 +92,10 @@ namespace MobileGL {
atOffset, data.size, m_size);
Memcpy(m_dataPtr->data() + atOffset, data.data, data.size);
m_dirtyRange.UnionUpdate(atOffset, atOffset + data.size);
m_change.DirtyRanges.Add({atOffset, atOffset + data.size});
m_change.Bits |= BufferChangeBits::DirtyBit;
m_change.Bits |= BufferChangeBits::ForbidInvalidationBit;
m_change.Bits |= BufferChangeBits::ForbidUnsynchronizationBit;
}
void BufferObject::CopyDataFrom(const SharedPtr<BufferObject>& src, SizeT srcOffset, SizeT dstOffset,
@@ -95,7 +111,8 @@ namespace MobileGL {
const Uint8* srcData = src->m_dataPtr->data() + srcOffset;
Memcpy(m_dataPtr->data() + dstOffset, srcData, size);
m_dirtyRange.UnionUpdate(dstOffset, dstOffset + size);
m_change.DirtyRanges.Add({dstOffset, dstOffset + size});
m_change.Bits |= BufferChangeBits::DirtyBit;
}
void* BufferObject::AcquireMemory(Bool markMapped, Bool read, Bool write) {
@@ -144,6 +161,14 @@ namespace MobileGL {
m_ownsStagingData = false;
return m_dataPtr->data() + range.start;
}
m_change.Bits |= !(access & BufferMappingAccessBit::InvalidateBuffer ||
access & BufferMappingAccessBit::InvalidateRange)
? BufferChangeBits::ForbidInvalidationBit
: BufferChangeBits::None;
m_change.Bits |= !(access & BufferMappingAccessBit::Unsynchronized)
? BufferChangeBits::ForbidUnsynchronizationBit
: BufferChangeBits::None;
}
const SharedPtr<Data> BufferObject::GetDataReadOnly() const {
@@ -151,7 +176,8 @@ namespace MobileGL {
}
void BufferObject::ClearDirty() {
m_dirtyRange = {0, 0};
m_change.DirtyRanges.clear();
m_change.Bits = BufferChangeBits::None;
}
SizeT BufferObject::GetSize() const {
@@ -162,8 +188,12 @@ namespace MobileGL {
return m_usage;
}
Range1D BufferObject::GetDirtyRange() const {
return m_dirtyRange;
const VecRange1D& BufferObject::GetDirtyRanges() const {
return m_change.DirtyRanges;
}
Flags<BufferChangeBits> BufferObject::GetChangeBits() const {
return m_change.Bits;
}
Bool BufferObject::IsMapped() const {
@@ -9,6 +9,7 @@
#pragma once
#include "MG_Util/Types.h"
#include <Includes.h>
#include <MG_Util/Math/VectorTypes.h>
namespace MobileGL {
enum class BufferTarget {
@@ -55,6 +56,23 @@ namespace MobileGL {
Coherent = 0x80
};
enum class BufferChangeBits : Uint8 {
None = 0,
DirtyBit = 1 << 0, // When not set, bits below are ignored and nothing should be synced to backend
PreferReallocationBit =
1 << 1, // <=> `glBufferData`; When set, ForbidInvalidationBit and ForbidUnsynchronizationBit are ignored
ForbidInvalidationBit = 1 << 2, // Indidate that invalidation flags were not used during mapping, else we're
// allowed to act as `GL_MAP_INVALIDATE_*` in backend
ForbidUnsynchronizationBit = 1 << 3, // (the same description as above, but for unsynchronization)
};
struct BufferChange {
static constexpr int DEFAULT_RESERVED_DIRTY_RANGES_COUNT = 50;
Flags<BufferChangeBits> Bits = BufferChangeBits::None;
VecRange1D DirtyRanges;
};
namespace MG_State {
namespace GLState {
class BufferObject {
@@ -77,11 +95,12 @@ namespace MobileGL {
Bool IsMapped() const;
SizeT GetSize() const;
BufferUsage GetUsage() const;
Range1D GetDirtyRange() const;
Range1D GetMappedRange() const;
const SharedPtr<Data> GetDataReadOnly() const;
Flags<BufferMappingAccessBit> GetMappingAccess() const;
Uint GetExternalIndex() const;
const VecRange1D& GetDirtyRanges() const;
Flags<BufferChangeBits> GetChangeBits() const;
private:
const Uint m_externalIndex = 0;
@@ -90,7 +109,7 @@ namespace MobileGL {
SharedPtr<Data> m_dataPtr;
Bool m_isMapped;
Flags<BufferMappingAccessBit> m_mappingAccess;
Range1D m_dirtyRange;
BufferChange m_change;
Range1D m_mappedRange;
Vector<Uint8> m_stagingData;
Bool m_ownsStagingData;
+8
View File
@@ -220,6 +220,14 @@ namespace MobileGL {
}
// RenderState
Uint GLContext::GetRenderStateParametersVersion() const {
return m_renderState.GetVersion();
}
const RenderStateParameters& GLContext::GetRenderStateParameters() const {
return m_renderState.GetAllParameters();
}
void GLContext::SetViewport(IntVec4 viewport) {
m_renderState.SetViewport(viewport);
}
+2
View File
@@ -86,6 +86,8 @@ namespace MobileGL {
SharedPtr<ProgramObject> GetCurrentProgram();
// RenderState
Uint GetRenderStateParametersVersion() const;
const RenderStateParameters& GetRenderStateParameters() const;
void SetViewport(IntVec4 viewport); // x, y, width, height
const IntVec4& GetViewport() const; // x, y, width, height
void SetCapability(CapabilityInput cap, Bool enabled);
@@ -12,41 +12,41 @@
namespace MobileGL {
namespace MG_State {
namespace GLState {
// FramebufferAttachment
FramebufferAttachment::FramebufferAttachment(SharedPtr<MG_State::GLState::ITextureObject> texture,
Int level)
// FramebufferAttachmentObject
FramebufferAttachmentObject::FramebufferAttachmentObject(SharedPtr<MG_State::GLState::ITextureObject> texture,
Int level)
: m_texture(texture), m_textureLevel(level) {}
FramebufferAttachment::FramebufferAttachment(SharedPtr<RenderbufferObject> renderbuffer)
FramebufferAttachmentObject::FramebufferAttachmentObject(SharedPtr<RenderbufferObject> renderbuffer)
: m_renderbuffer(renderbuffer) {}
FramebufferAttachment::FramebufferAttachment(Bool IsValid) : m_texture(nullptr), m_renderbuffer(nullptr) {
FramebufferAttachmentObject::FramebufferAttachmentObject(Bool IsValid) : m_texture(nullptr), m_renderbuffer(nullptr) {
m_isValid = IsValid;
}
Bool FramebufferAttachment::IsTexture() const {
Bool FramebufferAttachmentObject::IsTexture() const {
return m_texture != nullptr;
}
Bool FramebufferAttachment::IsRenderbuffer() const {
Bool FramebufferAttachmentObject::IsRenderbuffer() const {
return m_renderbuffer != nullptr;
}
Bool FramebufferAttachment::IsEmpty() const {
Bool FramebufferAttachmentObject::IsEmpty() const {
return m_texture == nullptr && m_renderbuffer == nullptr;
}
SharedPtr<MG_State::GLState::ITextureObject> FramebufferAttachment::GetTexture() const {
SharedPtr<MG_State::GLState::ITextureObject> FramebufferAttachmentObject::GetTexture() const {
return m_texture;
}
SharedPtr<RenderbufferObject> FramebufferAttachment::GetRenderbuffer() const {
SharedPtr<RenderbufferObject> FramebufferAttachmentObject::GetRenderbuffer() const {
return m_renderbuffer;
}
Int FramebufferAttachment::GetTextureLevel() const {
Int FramebufferAttachmentObject::GetTextureLevel() const {
return m_textureLevel;
}
Bool FramebufferAttachment::IsComplete() const {
Bool FramebufferAttachmentObject::IsComplete() const {
if (IsTexture()) {
Bool complete = m_texture->IsComplete();
return complete;
@@ -58,7 +58,7 @@ namespace MobileGL {
return false;
}
IntVec3 FramebufferAttachment::GetSize() const {
IntVec3 FramebufferAttachmentObject::GetSize() const {
if (IsTexture()) {
// TODO: get correct upload target
MOBILEGL_ASSERT(nullptr != dynamic_cast<MG_State::GLState::TextureObjectMipmap*>(m_texture.get()),
@@ -71,56 +71,55 @@ namespace MobileGL {
return {0, 0, 0};
}
Bool FramebufferAttachment::IsValid() const {
Bool FramebufferAttachmentObject::IsValid() const {
return m_isValid;
}
// FramebufferObject
FramebufferObject::FramebufferObject(Uint externalIndex) : m_externalIndex(externalIndex) {
m_attachments.fill(FramebufferAttachment(false));
m_attachmentObjects.fill(FramebufferAttachmentObject(false));
m_drawBuffers.fill(FramebufferAttachmentType::None);
m_drawBuffers[0] = FramebufferAttachmentType::Color0;
m_attachmentVersions.fill(0);
}
void FramebufferObject::AttachTexture(FramebufferAttachmentType type, SharedPtr<ITextureObject> texture,
int level) {
m_attachments[static_cast<SizeT>(type)] = FramebufferAttachment(std::move(texture), level);
m_drawBuffersDirty = true;
m_attachmentObjects[static_cast<SizeT>(type)] = FramebufferAttachmentObject(std::move(texture), level);
BumpAttachmentVersion(type);
}
void FramebufferObject::AttachRenderbuffer(FramebufferAttachmentType type,
std::shared_ptr<RenderbufferObject> renderbuffer) {
m_attachments[static_cast<SizeT>(type)] = FramebufferAttachment(renderbuffer);
m_drawBuffersDirty = true;
m_attachmentObjects[static_cast<SizeT>(type)] = FramebufferAttachmentObject(renderbuffer);
BumpAttachmentVersion(type);
}
void FramebufferObject::Detach(FramebufferAttachmentType type) {
m_attachments[static_cast<SizeT>(type)] = FramebufferAttachment(false);
m_drawBuffersDirty = true;
m_attachmentObjects[static_cast<SizeT>(type)] = FramebufferAttachmentObject(false);
BumpAttachmentVersion(type);
}
const FramebufferAttachment& FramebufferObject::GetAttachment(FramebufferAttachmentType type) const {
return m_attachments[static_cast<SizeT>(type)];
const FramebufferAttachmentObject& FramebufferObject::GetAttachment(FramebufferAttachmentType type) const {
return m_attachmentObjects[static_cast<SizeT>(type)];
}
const Array<FramebufferAttachment,
static_cast<SizeT>(FramebufferAttachmentType::FramebufferAttachmentTypeCount)>&
FramebufferObject::GetAllAttachments() const {
return m_attachments;
const FramebufferObject::FramebufferAttachmentObjectArray& FramebufferObject::GetAllAttachmentObjects() const {
return m_attachmentObjects;
}
Bool FramebufferObject::CheckCompleteness() const {
if (m_attachments.empty()) {
if (m_attachmentObjects.empty()) {
return false;
}
Int width = -1, height = -1;
Int validAttachmentCount = 0;
for (SizeT i = 0; i < m_attachments.size(); ++i) {
if (!m_attachments[i].IsValid()) continue;
for (SizeT i = 0; i < m_attachmentObjects.size(); ++i) {
if (!m_attachmentObjects[i].IsValid()) continue;
++validAttachmentCount;
const auto& attachment = m_attachments[i];
const auto& attachment = m_attachmentObjects[i];
auto attachmentSize = attachment.GetSize();
Int w = attachmentSize.x();
Int h = attachmentSize.y();
@@ -143,26 +142,22 @@ namespace MobileGL {
void FramebufferObject::SetDrawBuffer(Uint index, FramebufferAttachmentType buffer) {
if (m_drawBuffers[index] == buffer) return;
m_drawBuffersDirty = true;
m_drawBuffers[index] = buffer;
BumpAttachmentVersion(buffer);
}
// void FramebufferObject::SetDrawBuffers(const Vector<FramebufferAttachmentType>& buffers) {
// m_drawBuffers = buffers;
// m_drawBuffersDirty = true;
// }
// void SetDrawBuffer(Uint index, FramebufferAttachmentType buffer) {
//
// }
const Array<FramebufferAttachmentType, FramebufferObject::MAX_DRAW_BUFFERS>& FramebufferObject::
GetDrawBuffers() const {
const FramebufferObject::FramebufferAttachmentArray& FramebufferObject::GetDrawBuffers() const {
return m_drawBuffers;
}
Uint FramebufferObject::GetExternalIndex() const {
return m_externalIndex;
}
void FramebufferObject::BumpAttachmentVersion(FramebufferAttachmentType type) {
++m_attachmentVersions[static_cast<SizeT>(type)];
++m_objectVersion;
}
} // namespace GLState
} // namespace MG_State
} // namespace MobileGL
@@ -69,11 +69,12 @@ namespace MobileGL {
namespace MG_State {
namespace GLState {
class FramebufferAttachment {
class FramebufferAttachmentObject {
public:
explicit FramebufferAttachment(SharedPtr<MG_State::GLState::ITextureObject> texture, Int level = 0);
explicit FramebufferAttachment(SharedPtr<RenderbufferObject> renderbuffer);
explicit FramebufferAttachment(Bool IsValid = true);
explicit FramebufferAttachmentObject(SharedPtr<MG_State::GLState::ITextureObject> texture,
Int level = 0);
explicit FramebufferAttachmentObject(SharedPtr<RenderbufferObject> renderbuffer);
explicit FramebufferAttachmentObject(Bool IsValid = true);
Bool IsTexture() const;
Bool IsRenderbuffer() const;
@@ -94,36 +95,51 @@ namespace MobileGL {
class FramebufferObject {
public:
using TargetEnum = FramebufferTarget;
static constexpr Uint MAX_DRAW_BUFFERS = 8;
using TargetEnum = FramebufferTarget;
using FramebufferAttachmentObjectArray =
Array<FramebufferAttachmentObject,
static_cast<SizeT>(FramebufferAttachmentType::FramebufferAttachmentTypeCount)>;
using FramebufferAttachmentArray = Array<FramebufferAttachmentType, MAX_DRAW_BUFFERS>;
using FramebufferAttachmentVersionArray =
Array<Uint16, static_cast<SizeT>(FramebufferAttachmentType::FramebufferAttachmentTypeCount)>;
FramebufferObject(Uint externalIndex);
void AttachTexture(FramebufferAttachmentType type, SharedPtr<ITextureObject> texture, int level = 0);
void AttachRenderbuffer(FramebufferAttachmentType type,
std::shared_ptr<RenderbufferObject> renderbuffer);
void Detach(FramebufferAttachmentType type);
const FramebufferAttachment& GetAttachment(FramebufferAttachmentType type) const;
const Array<FramebufferAttachment,
static_cast<SizeT>(FramebufferAttachmentType::FramebufferAttachmentTypeCount)>&
GetAllAttachments() const;
const FramebufferAttachmentObject& GetAttachment(FramebufferAttachmentType type) const;
const FramebufferAttachmentObjectArray& GetAllAttachmentObjects() const;
Bool CheckCompleteness() const;
// aka. `buffer` as in glDrawBuffers/glReadBuffers
void SetDrawBuffer(Uint index, FramebufferAttachmentType buffer);
bool DrawBuffersIsDirty() const { return m_drawBuffersDirty; }
void ClearDrawBuffersDirtyState() { m_drawBuffersDirty = false; }
const Array<FramebufferAttachmentType, MAX_DRAW_BUFFERS>& GetDrawBuffers() const;
const FramebufferAttachmentArray& GetDrawBuffers() const;
void SetReadBuffer(FramebufferAttachmentType buf) { m_readBuffer = buf; }
FramebufferAttachmentType GetReadBuffer() const { return m_readBuffer; }
const FramebufferAttachmentVersionArray GetAllFramebufferAttachmentVersions() const {
return m_attachmentVersions;
}
Uint16 GetObjectVersion() const { return m_objectVersion; }
Uint GetExternalIndex() const;
private:
void BumpAttachmentVersion(FramebufferAttachmentType type);
const Uint m_externalIndex = 0;
Array<FramebufferAttachment,
static_cast<SizeT>(FramebufferAttachmentType::FramebufferAttachmentTypeCount)>
m_attachments;
Bool m_drawBuffersDirty = false;
Array<FramebufferAttachmentType, MAX_DRAW_BUFFERS> m_drawBuffers;
FramebufferAttachmentType m_readBuffer = FramebufferAttachmentType::Color0;
FramebufferAttachmentObjectArray m_attachmentObjects;
FramebufferAttachmentVersionArray m_attachmentVersions;
FramebufferAttachmentArray m_drawBuffers; // Probably no versioning needed for this, just check equality
FramebufferAttachmentType m_readBuffer = FramebufferAttachmentType::Color0; // ditto
// This version will bump when draw/read buffer changes (by `glDrawBuffer(s)`/`glReadBuffer`)
Uint16 m_objectVersion = 0;
};
} // namespace GLState
@@ -453,7 +453,7 @@ namespace MobileGL {
MGLOG_D("ProgramObject %u: GenerateBinary - generated %zu SPIR-V modules", m_externalIndex,
m_generatedSpirv.size());
for (auto& spv: m_generatedSpirv) {
for (auto& spv : m_generatedSpirv) {
auto success = ShaderCompiler::SanitizeAndOptimizeBinary(spv, spv);
MOBILEGL_ASSERT(success, "SanitizeBinary failed");
}
@@ -42,7 +42,8 @@ namespace MobileGL {
} else {
m_compileStatus = false;
m_infoLog = result.error().log;
MGLOG_D("ShaderObject::Compile: Shader %d compilation failed.\nSource:\n%s\nInfoLog:\n%s\nSetting m_compileStatus = false as a result.",
MGLOG_D("ShaderObject::Compile: Shader %d compilation failed.\nSource:\n%s\nInfoLog:\n%s\nSetting "
"m_compileStatus = false as a result.",
m_externalIndex, m_source.c_str(), m_infoLog.c_str());
}
}
@@ -13,45 +13,55 @@ namespace MobileGL {
namespace GLState {
RenderState::RenderState() {}
Uint RenderState::GetVersion() const {
return m_version;
}
const RenderStateParameters& RenderState::GetAllParameters() const {
return m_parameters;
}
// -------------------- Rasterization --------------------
void RenderState::SetViewport(IntVec4 viewport) {
m_viewport = viewport;
if (m_parameters.Viewport == viewport) return;
m_parameters.Viewport = viewport;
++m_version;
}
const IntVec4& RenderState::GetViewport() const {
return m_viewport;
return m_parameters.Viewport;
}
// -------------------- Capabilities --------------------
void RenderState::SetCapability(CapabilityInput cap, Bool enabled) {
#define SET_CAPABILITY(capability, flag) \
case CapabilityInput::capability: \
if (m_parameters.capability##Enabled == flag) break; \
m_parameters.capability##Enabled = flag; \
++m_version; \
break;
switch (cap) {
case CapabilityInput::Blend:
m_blendEnabled = enabled;
break;
case CapabilityInput::DepthTest:
m_depthTestEnabled = enabled;
break;
case CapabilityInput::CullFace:
m_cullFaceEnabled = enabled;
break;
case CapabilityInput::ScissorTest:
m_scissorTestEnabled = enabled;
break;
SET_CAPABILITY(Blend, enabled);
SET_CAPABILITY(DepthTest, enabled);
SET_CAPABILITY(CullFace, enabled);
SET_CAPABILITY(ScissorTest, enabled);
default: // not supported currently
break;
}
#undef SET_CAPABILITY
}
Bool RenderState::IsCapabilityEnabled(CapabilityInput cap) const {
#define RETURN_CAPABILITY(capability) \
case CapabilityInput::capability: \
return m_parameters.capability##Enabled;
switch (cap) {
case CapabilityInput::Blend:
return m_blendEnabled;
case CapabilityInput::DepthTest:
return m_depthTestEnabled;
case CapabilityInput::CullFace:
return m_cullFaceEnabled;
case CapabilityInput::ScissorTest:
return m_scissorTestEnabled;
RETURN_CAPABILITY(Blend);
RETURN_CAPABILITY(DepthTest);
RETURN_CAPABILITY(CullFace);
RETURN_CAPABILITY(ScissorTest);
default:
return false;
}
@@ -60,115 +70,108 @@ namespace MobileGL {
// -------------------- Blending --------------------
void RenderState::SetBlendFunc(BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha,
BlendFactor dstAlpha) {
m_srcFactorRGB = srcRGB;
m_dstFactorRGB = dstRGB;
m_srcFactorAlpha = srcAlpha;
m_dstFactorAlpha = dstAlpha;
if (m_parameters.SrcFactorRGB == srcRGB && m_parameters.DstFactorRGB == dstRGB &&
m_parameters.SrcFactorAlpha == srcAlpha && m_parameters.DstFactorAlpha == dstAlpha)
return;
m_parameters.SrcFactorRGB = srcRGB;
m_parameters.DstFactorRGB = dstRGB;
m_parameters.SrcFactorAlpha = srcAlpha;
m_parameters.DstFactorAlpha = dstAlpha;
++m_version;
}
void RenderState::GetBlendFunc(BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha,
BlendFactor& dstAlpha) const {
srcRGB = m_srcFactorRGB;
dstRGB = m_dstFactorRGB;
srcAlpha = m_srcFactorAlpha;
dstAlpha = m_dstFactorAlpha;
srcRGB = m_parameters.SrcFactorRGB;
dstRGB = m_parameters.DstFactorRGB;
srcAlpha = m_parameters.SrcFactorAlpha;
dstAlpha = m_parameters.DstFactorAlpha;
}
// -------------------- Depth --------------------
void RenderState::SetDepthFunc(DepthTestFunc func) {
m_depthFunc = func;
if (m_parameters.DepthFunc == func) return;
m_parameters.DepthFunc = func;
++m_version;
}
DepthTestFunc RenderState::GetDepthFunc() const {
return m_depthFunc;
return m_parameters.DepthFunc;
}
void RenderState::SetDepthMask(Bool flag) {
m_depthMask = flag;
if (m_parameters.DepthMask == flag) return;
m_parameters.DepthMask = flag;
++m_version;
}
Bool RenderState::GetDepthMask() const {
return m_depthMask;
return m_parameters.DepthMask;
}
// -------------------- Color Mask --------------------
void RenderState::SetColorMask(BoolVec4 mask) {
m_colorMask = mask;
if (m_parameters.ColorMask == mask) return;
m_parameters.ColorMask = mask;
++m_version;
}
const BoolVec4 RenderState::GetColorMask() const {
return m_colorMask;
return m_parameters.ColorMask;
}
// -------------------- Clear State --------------------
void RenderState::SetClearColor(FloatVec4 color) {
m_clearColor = color;
if (m_parameters.ClearColor == color) return;
m_parameters.ClearColor = color;
++m_version;
}
const FloatVec4& RenderState::GetClearColor() const {
return m_clearColor;
return m_parameters.ClearColor;
}
void RenderState::SetClearDepth(Float depth) {
m_clearDepth = depth;
if (m_parameters.ClearDepth == depth) return;
m_parameters.ClearDepth = depth;
++m_version;
}
Float RenderState::GetClearDepth() const {
return m_clearDepth;
return m_parameters.ClearDepth;
}
// -------------------- Pixel Store --------------------
void RenderState::SetPixelStoreParam(PixelStoreParam param, Int value) {
#define SET_PIXEL_STORE_PARAM(paramNameHead, paramNameTail, val) \
case PixelStoreParam::paramNameHead##paramNameTail: \
if (m_pixelStore##paramNameHead##Parameters.paramNameTail == val) break; \
m_pixelStore##paramNameHead##Parameters.paramNameTail = val; \
break;
switch (param) {
case PixelStoreParam::PackAlignment:
m_packParameters.Alignment = value;
break;
case PixelStoreParam::PackRowLength:
m_packParameters.RowLength = value;
break;
case PixelStoreParam::PackImageHeight:
m_packParameters.ImageHeight = value;
break;
case PixelStoreParam::PackSkipPixels:
m_packParameters.SkipPixels = value;
break;
case PixelStoreParam::PackSkipRows:
m_packParameters.SkipRows = value;
break;
case PixelStoreParam::PackSkipImages:
m_packParameters.SkipImages = value;
break;
case PixelStoreParam::PackSwapBytes:
m_packParameters.SwapBytes = value != 0;
break;
case PixelStoreParam::PackLsbFirst:
m_packParameters.LSBFirst = value != 0;
break;
case PixelStoreParam::UnpackAlignment:
m_unpackParameters.Alignment = value;
break;
case PixelStoreParam::UnpackRowLength:
m_unpackParameters.RowLength = value;
break;
case PixelStoreParam::UnpackImageHeight:
m_unpackParameters.ImageHeight = value;
break;
case PixelStoreParam::UnpackSkipPixels:
m_unpackParameters.SkipPixels = value;
break;
case PixelStoreParam::UnpackSkipRows:
m_unpackParameters.SkipRows = value;
break;
case PixelStoreParam::UnpackSkipImages:
m_unpackParameters.SkipImages = value;
break;
case PixelStoreParam::UnpackSwapBytes:
m_unpackParameters.SwapBytes = value != 0;
MGLOG_D("%s: SwapBytes = %s", __func__, value ? "true" : "false");
break;
case PixelStoreParam::UnpackLsbFirst:
m_unpackParameters.LSBFirst = value != 0;
break;
SET_PIXEL_STORE_PARAM(Pack, Alignment, value);
SET_PIXEL_STORE_PARAM(Pack, RowLength, value);
SET_PIXEL_STORE_PARAM(Pack, ImageHeight, value);
SET_PIXEL_STORE_PARAM(Pack, SkipPixels, value);
SET_PIXEL_STORE_PARAM(Pack, SkipRows, value);
SET_PIXEL_STORE_PARAM(Pack, SkipImages, value);
SET_PIXEL_STORE_PARAM(Pack, SwapBytes, value != 0);
SET_PIXEL_STORE_PARAM(Pack, LSBFirst, value != 0);
SET_PIXEL_STORE_PARAM(Unpack, Alignment, value);
SET_PIXEL_STORE_PARAM(Unpack, RowLength, value);
SET_PIXEL_STORE_PARAM(Unpack, ImageHeight, value);
SET_PIXEL_STORE_PARAM(Unpack, SkipPixels, value);
SET_PIXEL_STORE_PARAM(Unpack, SkipRows, value);
SET_PIXEL_STORE_PARAM(Unpack, SkipImages, value);
SET_PIXEL_STORE_PARAM(Unpack, SwapBytes, value != 0);
SET_PIXEL_STORE_PARAM(Unpack, LSBFirst, value != 0);
default:
MOBILEGL_ASSERT(false, "Invalid PixelStoreParam enum: %d", static_cast<int>(param));
return;
@@ -176,39 +179,26 @@ namespace MobileGL {
}
Int RenderState::GetPixelStoreParam(PixelStoreParam param) const {
#define RETURN_PIXEL_STORE_PARAM(paramNameHead, paramNameTail) \
case PixelStoreParam::paramNameHead##paramNameTail: \
return m_pixelStore##paramNameHead##Parameters.paramNameTail;
switch (param) {
case PixelStoreParam::PackAlignment:
return m_packParameters.Alignment;
case PixelStoreParam::PackRowLength:
return m_packParameters.RowLength;
case PixelStoreParam::PackImageHeight:
return m_packParameters.ImageHeight;
case PixelStoreParam::PackSkipPixels:
return m_packParameters.SkipPixels;
case PixelStoreParam::PackSkipRows:
return m_packParameters.SkipRows;
case PixelStoreParam::PackSkipImages:
return m_packParameters.SkipImages;
case PixelStoreParam::PackSwapBytes:
return m_packParameters.SwapBytes ? 1 : 0;
case PixelStoreParam::PackLsbFirst:
return m_packParameters.LSBFirst ? 1 : 0;
case PixelStoreParam::UnpackAlignment:
return m_unpackParameters.Alignment;
case PixelStoreParam::UnpackRowLength:
return m_unpackParameters.RowLength;
case PixelStoreParam::UnpackImageHeight:
return m_unpackParameters.ImageHeight;
case PixelStoreParam::UnpackSkipPixels:
return m_unpackParameters.SkipPixels;
case PixelStoreParam::UnpackSkipRows:
return m_unpackParameters.SkipRows;
case PixelStoreParam::UnpackSkipImages:
return m_unpackParameters.SkipImages;
case PixelStoreParam::UnpackSwapBytes:
return m_unpackParameters.SwapBytes ? 1 : 0;
case PixelStoreParam::UnpackLsbFirst:
return m_unpackParameters.LSBFirst ? 1 : 0;
RETURN_PIXEL_STORE_PARAM(Pack, Alignment);
RETURN_PIXEL_STORE_PARAM(Pack, RowLength);
RETURN_PIXEL_STORE_PARAM(Pack, ImageHeight);
RETURN_PIXEL_STORE_PARAM(Pack, SkipPixels);
RETURN_PIXEL_STORE_PARAM(Pack, SkipRows);
RETURN_PIXEL_STORE_PARAM(Pack, SkipImages);
RETURN_PIXEL_STORE_PARAM(Pack, SwapBytes);
RETURN_PIXEL_STORE_PARAM(Pack, LSBFirst);
RETURN_PIXEL_STORE_PARAM(Unpack, Alignment);
RETURN_PIXEL_STORE_PARAM(Unpack, RowLength);
RETURN_PIXEL_STORE_PARAM(Unpack, ImageHeight);
RETURN_PIXEL_STORE_PARAM(Unpack, SkipPixels);
RETURN_PIXEL_STORE_PARAM(Unpack, SkipRows);
RETURN_PIXEL_STORE_PARAM(Unpack, SkipImages);
RETURN_PIXEL_STORE_PARAM(Unpack, SwapBytes);
RETURN_PIXEL_STORE_PARAM(Unpack, LSBFirst);
default:
MOBILEGL_ASSERT(false, "Invalid PixelStoreParam enum: %d", static_cast<int>(param));
return 0;
@@ -216,25 +206,31 @@ namespace MobileGL {
}
PixelStoreParameters RenderState::GetPixelStoreParameters(Bool isUnpack) const {
return isUnpack ? m_unpackParameters : m_packParameters;
return isUnpack ? m_pixelStoreUnpackParameters : m_pixelStorePackParameters;
}
// -------------------- Cull Face --------------------
void RenderState::SetCullFaceMode(CullFaceMode mode) {
m_cullFaceMode = mode;
if (m_parameters.CullFaceModeSetting == mode) return;
m_parameters.CullFaceModeSetting = mode;
++m_version;
}
CullFaceMode RenderState::GetCullFaceMode() const {
return m_cullFaceMode;
return m_parameters.CullFaceModeSetting;
}
// --------------------- Scissor ---------------------
void RenderState::SetScissorBox(IntVec4 box) {
m_scissorBox = box;
if (m_parameters.ScissorBox == box) return;
m_parameters.ScissorBox = box;
++m_version;
}
const IntVec4& RenderState::GetScissorBox() const {
return m_scissorBox;
return m_parameters.ScissorBox;
}
} // namespace GLState
} // namespace MG_State
@@ -7,9 +7,8 @@
// End of Source File Header
#pragma once
#include "MG_Util/Math/VectorTypes.h"
#include "MG_Util/Types.h"
#include <Includes.h>
#include <MG_Util/Math/VectorTypes.h>
namespace MobileGL {
enum class BlendFactor {
@@ -53,7 +52,7 @@ namespace MobileGL {
PackSkipPixels,
PackSkipImages,
PackSwapBytes,
PackLsbFirst,
PackLSBFirst,
// Unpack Parameters
UnpackAlignment,
@@ -63,7 +62,7 @@ namespace MobileGL {
UnpackSkipPixels,
UnpackSkipImages,
UnpackSwapBytes,
UnpackLsbFirst,
UnpackLSBFirst,
PixelStoreParamCount,
Unknown = -1
@@ -128,12 +127,47 @@ namespace MobileGL {
Int Alignment = 4;
};
struct RenderStateParameters {
// Rasterization
IntVec4 Viewport = IntVec4(0, 0, 0, 0); // x, y, width, height
// Blending
Bool BlendEnabled = false;
BlendFactor SrcFactorRGB = BlendFactor::One;
BlendFactor DstFactorRGB = BlendFactor::Zero;
BlendFactor SrcFactorAlpha = BlendFactor::One;
BlendFactor DstFactorAlpha = BlendFactor::Zero;
// Depth
Bool DepthTestEnabled = false;
DepthTestFunc DepthFunc = DepthTestFunc::Less;
Bool DepthMask = true;
// Color Mask
BoolVec4 ColorMask = BoolVec4(true, true, true, true);
// Clear State
FloatVec4 ClearColor = FloatVec4(0.0f, 0.0f, 0.0f, 1.0f);
Float ClearDepth = 1.0f;
// Cull Face
Bool CullFaceEnabled = false;
CullFaceMode CullFaceModeSetting = CullFaceMode::Back;
// Scissor
Bool ScissorTestEnabled = false;
IntVec4 ScissorBox = IntVec4(0, 0, 0, 0); // x, y, width, height
};
namespace MG_State {
namespace GLState {
class RenderState {
public:
RenderState();
Uint GetVersion() const;
const RenderStateParameters& GetAllParameters() const;
// Rasterization
void SetViewport(IntVec4 viewport); // x, y, width, height
const IntVec4& GetViewport() const; // x, y, width, height
@@ -177,39 +211,12 @@ namespace MobileGL {
const IntVec4& GetScissorBox() const; // x, y, width, height
private:
// Rasterization
IntVec4 m_viewport = IntVec4(0, 0, 0, 0); // x, y, width, height
// Blending
Bool m_blendEnabled = false;
BlendFactor m_srcFactorRGB = BlendFactor::One;
BlendFactor m_dstFactorRGB = BlendFactor::Zero;
BlendFactor m_srcFactorAlpha = BlendFactor::One;
BlendFactor m_dstFactorAlpha = BlendFactor::Zero;
// Depth
Bool m_depthTestEnabled = false;
DepthTestFunc m_depthFunc = DepthTestFunc::Less;
Bool m_depthMask = true;
// Color Mask
BoolVec4 m_colorMask = BoolVec4(true, true, true, true);
// Clear State
FloatVec4 m_clearColor = FloatVec4(0.0f, 0.0f, 0.0f, 1.0f);
Float m_clearDepth = 1.0f;
Uint16 m_version = 0;
RenderStateParameters m_parameters;
// Pixel Store
PixelStoreParameters m_packParameters;
PixelStoreParameters m_unpackParameters;
// Cull Face
Bool m_cullFaceEnabled = false;
CullFaceMode m_cullFaceMode = CullFaceMode::Back;
// Scissor
Bool m_scissorTestEnabled = false;
IntVec4 m_scissorBox = IntVec4(0, 0, 0, 0); // x, y, width, height
PixelStoreParameters m_pixelStorePackParameters;
PixelStoreParameters m_pixelStoreUnpackParameters;
};
} // namespace GLState
} // namespace MG_State
@@ -14,47 +14,77 @@ namespace MobileGL {
SamplerObject::SamplerObject(Uint externalIndex) : m_externalIndex(externalIndex) {}
void SamplerObject::SetWrapS(SamplerWrapMode mode) {
if (mode == m_samplerParameters.wrapS) return;
m_samplerParameters.wrapS = mode;
++m_version;
}
void SamplerObject::SetWrapT(SamplerWrapMode mode) {
if (mode == m_samplerParameters.wrapT) return;
m_samplerParameters.wrapT = mode;
++m_version;
}
void SamplerObject::SetWrapR(SamplerWrapMode mode) {
if (mode == m_samplerParameters.wrapR) return;
m_samplerParameters.wrapR = mode;
++m_version;
}
void SamplerObject::SetMinFilter(SamplerFilterMode mode) {
if (mode == m_samplerParameters.minFilter) return;
m_samplerParameters.minFilter = mode;
++m_version;
}
void SamplerObject::SetMagFilter(SamplerFilterMode mode) {
if (mode == m_samplerParameters.magFilter) return;
m_samplerParameters.magFilter = mode;
++m_version;
}
void SamplerObject::SetMipmapMode(SamplerMipmapMode mode) {
if (mode == m_samplerParameters.mipmapMode) return;
m_samplerParameters.mipmapMode = mode;
++m_version;
}
void SamplerObject::SetLodRange(Float minLod, Float maxLod) {
if (minLod == m_samplerParameters.minLod && maxLod == m_samplerParameters.maxLod) return;
if (minLod > maxLod) {
THROW_EXCEPTION("minLod cannot be greater than maxLod");
}
m_samplerParameters.minLod = minLod;
m_samplerParameters.maxLod = maxLod;
++m_version;
}
void SamplerObject::SetLodBias(Float bias) {
if (bias == m_samplerParameters.lodBias) return;
m_samplerParameters.lodBias = bias;
++m_version;
}
void SamplerObject::SetSamplerCompareFunc(SamplerCompareFunc func) {
if (func == m_samplerParameters.compareFunc) return;
m_samplerParameters.compareFunc = func;
++m_version;
}
void SamplerObject::SetCompareMode(SamplerCompareMode mode) {
if (mode == m_samplerParameters.compareMode) return;
m_samplerParameters.compareMode = mode;
++m_version;
}
SamplerWrapMode SamplerObject::GetWrapS() const {
@@ -108,6 +138,10 @@ namespace MobileGL {
const SamplerParameters& SamplerObject::GetAllSamplerParameters() const {
return m_samplerParameters;
}
Uint16 SamplerObject::GetVersion() const {
return m_version;
}
} // namespace GLState
} // namespace MG_State
} // namespace MobileGL
@@ -98,10 +98,12 @@ namespace MobileGL {
SamplerCompareMode GetCompareMode() const;
SamplerCompareFunc GetSamplerCompareFunc() const;
Uint GetExternalIndex() const;
Uint16 GetVersion() const;
const SamplerParameters& GetAllSamplerParameters() const;
private:
const Uint m_externalIndex;
Uint16 m_version = 0;
SamplerParameters m_samplerParameters;
};
} // namespace GLState
@@ -25,6 +25,7 @@ namespace MobileGL {
SizeT GetByteSize(Uint level) const;
void MarkDirty(Uint level, bool dirty);
bool IsDirty(Uint level) const;
protected:
Vector<IntVec3> m_texelSizes;
Vector<Vector<Uint8>> m_data;
@@ -19,7 +19,9 @@ namespace MobileGL {
template <SizeT TargetCount>
class MipmapUploadTargetArray {
public:
MipmapUploadTargetArray() { static_assert(TargetCount > 0, "Upload target count must be greater than zero"); }
MipmapUploadTargetArray() {
static_assert(TargetCount > 0, "Upload target count must be greater than zero");
}
void AllocateLevel(Uint targetIndex, Uint level, MipmapInput input) {
MOBILEGL_ASSERT(targetIndex < TargetCount, "AllocateLevel: target invalid");
@@ -7,6 +7,7 @@
// End of Source File Header
#include "TextureObject.h"
#include "MG_Util/Types.h"
#include <MG_Util/Metrics/TextureMetrics.h>
namespace MobileGL {
@@ -43,7 +44,10 @@ namespace MobileGL {
}
void TextureObjectBase::SetInternalFormat(TextureInternalFormat format) {
if (format == m_internalFormat) return;
m_internalFormat = format;
++m_textureParamsVersion;
}
Uint TextureObjectBase::GetExternalIndex() const {
@@ -55,7 +59,10 @@ namespace MobileGL {
}
void TextureObjectBase::SetBorderColor(const FloatVec4& color) {
if (color == m_borderColor) return;
m_borderColor = color;
++m_textureParamsVersion;
}
TextureSwizzleParam TextureObjectBase::GetSwizzleParam(TextureSwizzleParam param) const {
@@ -80,6 +87,8 @@ namespace MobileGL {
}
void TextureObjectBase::SetSwizzleParam(TextureSwizzleParam param, TextureSwizzleParam value) {
if (GetSwizzleParam(param) == value) return;
switch (param) {
case TextureSwizzleParam::Red:
m_swizzleParams.r() = value;
@@ -98,9 +107,14 @@ namespace MobileGL {
static_cast<Int>(param));
break;
}
++m_textureParamsVersion;
}
void TextureObjectBase::SetSwizzleParamRGBA(const Vec4<TextureSwizzleParam>& values) {
if (values == m_swizzleParams) return;
m_swizzleParams = values;
++m_textureParamsVersion;
}
const UintVec2& TextureObjectBase::GetLevelRange() const {
@@ -108,11 +122,21 @@ namespace MobileGL {
}
void TextureObjectBase::SetBaseLevel(Uint baseLevel) {
if (baseLevel == m_levelRange.x()) return;
m_levelRange.x() = baseLevel;
++m_textureParamsVersion;
}
void TextureObjectBase::SetMaxLevel(Uint maxLevel) {
if (maxLevel == m_levelRange.y()) return;
m_levelRange.y() = maxLevel;
++m_textureParamsVersion;
}
Uint16 TextureObjectBase::GetTextureParamsVersion() const {
return m_textureParamsVersion;
}
Uint TextureObjectWithOneMipmap::GetMipmapLevelCount() const {
@@ -144,11 +168,11 @@ namespace MobileGL {
}
void TextureObjectWithOneMipmap::MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel,
bool dirty) {
Bool dirty) {
m_textureStorage.MarkDirty(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel, dirty);
}
bool TextureObjectWithOneMipmap::IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const {
Bool TextureObjectWithOneMipmap::IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const {
return m_textureStorage.IsDirty(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel);
}
@@ -170,7 +194,7 @@ namespace MobileGL {
// For some reason mojang decided to have 0x0 in last level mipmap
// Relaxing checks for that
bool hadZero = false;
Bool hadZero = false;
for (SizeT i = 0; i < levelCount; ++i) {
const auto& levelSize = m_textureStorage.GetTexelSize(0, i);
if (levelSize.x() <= 0 || levelSize.y() <= 0 || levelSize.z() <= 0) {
@@ -41,6 +41,7 @@ namespace MobileGL {
virtual const UintVec2& GetLevelRange() const = 0;
virtual void SetBaseLevel(Uint baseLevel) = 0;
virtual void SetMaxLevel(Uint maxLevel) = 0;
virtual Uint16 GetTextureParamsVersion() const = 0;
protected:
virtual Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const = 0;
@@ -67,7 +68,7 @@ namespace MobileGL {
const UintVec2& GetLevelRange() const override;
void SetBaseLevel(Uint baseLevel) override;
void SetMaxLevel(Uint maxLevel) override;
Uint16 GetTextureParamsVersion() const override;
protected:
const Uint m_externalIndex;
const TextureTarget m_target = TextureTarget::Unknown;
@@ -77,11 +78,13 @@ namespace MobileGL {
Vec4<TextureSwizzleParam> m_swizzleParams = {TextureSwizzleParam::Red, TextureSwizzleParam::Green,
TextureSwizzleParam::Blue, TextureSwizzleParam::Alpha};
UintVec2 m_levelRange = {0, 1000};
Uint16 m_textureParamsVersion = 0;
};
class TextureObjectMipmap : public TextureObjectBase {
public:
TextureObjectMipmap(TextureTarget target, Uint externalIndex): TextureObjectBase(target, externalIndex) {}
TextureObjectMipmap(TextureTarget target, Uint externalIndex)
: TextureObjectBase(target, externalIndex) {}
TextureStorageType GetStorageType() const override { return TextureStorageType::Mipmap; }
@@ -91,8 +94,9 @@ namespace MobileGL {
virtual void AllocateStorage(TextureUploadTarget uploadTarget, Uint mipmapLevel, MipmapInput input) = 0;
virtual void UpdateMipmapSubData(TextureUploadTarget uploadTarget, Uint mipmapLevel, DataPtr input) = 0;
virtual void* MapMipmapData(TextureUploadTarget uploadTarget, Uint mipmapLevel) = 0;
virtual void MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel, bool dirty) = 0;
virtual bool IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const = 0;
virtual void MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel,
Bool dirty = true) = 0;
virtual Bool IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const = 0;
};
class TextureObjectWithOneMipmap : public TextureObjectMipmap {
@@ -107,7 +111,7 @@ namespace MobileGL {
void AllocateStorage(TextureUploadTarget uploadTarget, Uint mipmapLevel, MipmapInput input) override;
void UpdateMipmapSubData(TextureUploadTarget uploadTarget, Uint mipmapLevel, DataPtr input) override;
void* MapMipmapData(TextureUploadTarget uploadTarget, Uint mipmapLevel) override;
void MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel, bool dirty) override;
void MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel, Bool dirty) override;
bool IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const override;
IntVec3 GetBaseSize() const override;
@@ -18,7 +18,8 @@ namespace MobileGL {
TextureStorageType GetStorageType() const override { return TextureStorageType::Buffer; }
explicit TextureObjectBuffer(Uint externalIndex);
const Vector<TextureUploadTarget>& GetUploadTargets() const override { return m_uploadTargets; }
BindingSlot<BufferObject>& GetBufferBindingSlot(TextureUploadTarget target = TextureUploadTarget::TextureBuffer);
BindingSlot<BufferObject>& GetBufferBindingSlot(
TextureUploadTarget target = TextureUploadTarget::TextureBuffer);
protected:
Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const override;
@@ -22,20 +22,26 @@ namespace MobileGL {
attr.Offset = 0;
attr.Buffer = nullptr;
MarkAttributeDirty(index);
BumpAttributeFormatVersion(index);
}
}
void VertexArrayObject::EnableAttribute(Uint index) {
if (index >= MAX_VERTEX_ATTRIBS) return;
if (m_attributes[index].Enabled) return;
m_attributes[index].Enabled = true;
MarkAttributeDirty(index);
BumpAttributeSwitchVersion(index);
}
void VertexArrayObject::DisableAttribute(Uint index) {
if (index >= MAX_VERTEX_ATTRIBS) return;
if (!m_attributes[index].Enabled) return;
m_attributes[index].Enabled = false;
MarkAttributeDirty(index);
BumpAttributeSwitchVersion(index);
}
Bool VertexArrayObject::IsAttributeEnabled(Uint index) const {
@@ -47,6 +53,12 @@ namespace MobileGL {
SizeT offset, Bool isInteger) {
if (index >= MAX_VERTEX_ATTRIBS) return;
if (m_attributes[index].Size == size && m_attributes[index].Type == type &&
m_attributes[index].Normalized == normalized && m_attributes[index].Stride == stride &&
m_attributes[index].Offset == offset && m_attributes[index].IsInteger == isInteger) {
return;
}
if (size < 1 || size > 4) {
return;
}
@@ -59,13 +71,16 @@ namespace MobileGL {
attr.Offset = offset;
attr.IsInteger = isInteger;
MarkAttributeDirty(index);
BumpAttributeFormatVersion(index);
}
void VertexArrayObject::BindAttributeBuffer(Uint index, const SharedPtr<BufferObject>& buffer) {
if (index >= MAX_VERTEX_ATTRIBS) return;
if (m_attributes[index].Buffer == buffer) return;
m_attributes[index].Buffer = buffer;
MarkAttributeDirty(index);
BumpAttributeBufferVersion(index);
}
BindingSlot<BufferObject>& VertexArrayObject::GetIndexBufferBindingSlot() {
@@ -83,22 +98,6 @@ namespace MobileGL {
return m_attributes;
}
void VertexArrayObject::MarkAttributeDirty(Uint index) {
if (index >= MAX_VERTEX_ATTRIBS) return;
if (std::find(m_dirtyAttributes.begin(), m_dirtyAttributes.end(), index) != m_dirtyAttributes.end()) {
return;
}
m_dirtyAttributes.push_back(index);
}
const Vector<Uint>& VertexArrayObject::GetDirtyAttributeIndices() const {
return m_dirtyAttributes;
}
void VertexArrayObject::ClearDirtyAttributes() {
m_dirtyAttributes.clear();
}
Uint VertexArrayObject::GetExternalIndex() const {
return m_externalIndex;
}
@@ -107,13 +106,39 @@ namespace MobileGL {
if (index >= MAX_VERTEX_ATTRIBS) return;
if (m_attributes[index].Divisor == divisor) return;
m_attributes[index].Divisor = divisor;
MarkAttributeDirty(index);
BumpAttributeFormatVersion(index);
}
Uint VertexArrayObject::GetAttributeDivisor(Uint index) const {
if (index >= MAX_VERTEX_ATTRIBS) return 0;
return m_attributes[index].Divisor;
}
void VertexArrayObject::BumpAttributeFormatVersion(Uint index) {
if (index >= MAX_VERTEX_ATTRIBS) return;
++m_attributeVersions[index].FormatVersion;
}
void VertexArrayObject::BumpAttributeBufferVersion(Uint index) {
if (index >= MAX_VERTEX_ATTRIBS) return;
++m_attributeVersions[index].BufferVersion;
}
void VertexArrayObject::BumpAttributeSwitchVersion(Uint index) {
if (index >= MAX_VERTEX_ATTRIBS) return;
++m_attributeVersions[index].SwitchVersion;
}
const VertexAttributeVersion& VertexArrayObject::GetAttributeVersion(Uint index) const {
static VertexAttributeVersion emptyVersion;
if (index >= MAX_VERTEX_ATTRIBS) return emptyVersion;
return m_attributeVersions[index];
}
const Array<VertexAttributeVersion, VertexArrayObject::MAX_VERTEX_ATTRIBS>& VertexArrayObject::
GetAllAttributeVersions() const {
return m_attributeVersions;
}
} // namespace GLState
} // namespace MG_State
} // namespace MobileGL
@@ -9,6 +9,7 @@
#pragma once
#include <Includes.h>
#include "../BufferState/BufferObject.h"
#include "MG_Util/Types.h"
namespace MobileGL {
namespace MG_State {
@@ -25,6 +26,12 @@ namespace MobileGL {
SharedPtr<BufferObject> Buffer;
};
struct VertexAttributeVersion {
Uint16 FormatVersion = 0;
Uint16 BufferVersion = 0;
Uint16 SwitchVersion = 0;
};
class VertexArrayObject {
public:
static constexpr int MAX_VERTEX_ATTRIBS = 16;
@@ -45,19 +52,22 @@ namespace MobileGL {
const VertexAttribute& GetAttribute(Uint index) const;
const Array<VertexAttribute, MAX_VERTEX_ATTRIBS>& GetAllAttributes() const;
const Vector<Uint>& GetDirtyAttributeIndices() const;
void ClearDirtyAttributes();
Uint GetExternalIndex() const;
void SetAttributeDivisor(Uint index, Uint divisor);
Uint GetAttributeDivisor(Uint index) const;
const VertexAttributeVersion& GetAttributeVersion(Uint index) const;
const Array<VertexAttributeVersion, MAX_VERTEX_ATTRIBS>& GetAllAttributeVersions() const;
private:
void MarkAttributeDirty(Uint index);
void BumpAttributeFormatVersion(Uint index);
void BumpAttributeBufferVersion(Uint index);
void BumpAttributeSwitchVersion(Uint index);
const Uint m_externalIndex = 0;
Array<VertexAttribute, MAX_VERTEX_ATTRIBS> m_attributes;
Vector<Uint> m_dirtyAttributes;
Array<VertexAttributeVersion, MAX_VERTEX_ATTRIBS> m_attributeVersions;
BindingSlot<BufferObject> m_indexBufferBindingSlot;
};
} // namespace GLState
+18 -9
View File
@@ -72,7 +72,8 @@ TEST_F(BufferTest, PingPong) {
Vector<Int> bufdata(data.size());
memcpy(bufdata.data(), p, byteSize);
ASSERT_EQ(data, bufdata);
auto range = bufRead->GetDirtyRange();
ASSERT_EQ(bufRead->GetDirtyRanges().size() >= 1, true);
auto range = bufRead->GetDirtyRanges()[0];
ASSERT_EQ(range.start, 0);
ASSERT_EQ(range.end, byteSize);
}
@@ -122,7 +123,8 @@ TEST_F(BufferTest, AcquireMemory) {
void* p = bufObj->AcquireMemory(false, true, false);
memcpy(actual.data(), p, byteSize);
ASSERT_EQ(actual, expected);
auto dirty = bufObj->GetDirtyRange();
ASSERT_EQ(bufObj->GetDirtyRanges().size() >= 1, true);
auto dirty = bufObj->GetDirtyRanges()[0];
ASSERT_EQ(dirty.start, 0);
ASSERT_EQ(dirty.end, sizeof(Int) * 5);
@@ -150,7 +152,8 @@ TEST_F(BufferTest, AcquireMemoryRangeWithoutExplicit) {
void* p = bufObj->AcquireMemory(false, true, false);
memcpy(actual.data(), p, byteSize);
ASSERT_EQ(actual, expected);
auto dirty = bufObj->GetDirtyRange();
ASSERT_EQ(bufObj->GetDirtyRanges().size() >= 1, true);
auto dirty = bufObj->GetDirtyRanges()[0];
ASSERT_EQ(dirty.start, sizeof(Int));
ASSERT_EQ(dirty.end, sizeof(Int) * 4);
}
@@ -177,13 +180,15 @@ TEST_F(BufferTest, AcquireMemoryRangeWithExplicit) {
mappedPtr[1] = 300;
bufObj->FlushMemoryRange(0, sizeof(Int));
auto dirty = bufObj->GetDirtyRange();
ASSERT_EQ(bufObj->GetDirtyRanges().size() >= 1, true);
auto dirty = bufObj->GetDirtyRanges()[0];
ASSERT_EQ(dirty.start, sizeof(Int));
ASSERT_EQ(dirty.end, sizeof(Int) * 2);
bufObj->ReleaseMemory();
dirty = bufObj->GetDirtyRange();
ASSERT_EQ(bufObj->GetDirtyRanges().size() >= 1, true);
dirty = bufObj->GetDirtyRanges()[0];
ASSERT_EQ(dirty.start, sizeof(Int));
ASSERT_EQ(dirty.end, sizeof(Int) * 2);
@@ -193,7 +198,8 @@ TEST_F(BufferTest, AcquireMemoryRangeWithExplicit) {
memcpy(actual.data(), p, byteSize);
ASSERT_EQ(actual, expected);
dirty = bufObj->GetDirtyRange();
ASSERT_EQ(bufObj->GetDirtyRanges().size() >= 1, true);
dirty = bufObj->GetDirtyRanges()[0];
ASSERT_EQ(dirty.start, sizeof(Int));
ASSERT_EQ(dirty.end, sizeof(Int) * 2);
}
@@ -235,7 +241,8 @@ TEST_F(BufferTest, CopyBufferSubData) {
ASSERT_EQ(actual, expected);
auto dirty = dstObj->GetDirtyRange();
ASSERT_EQ(dstObj->GetDirtyRanges().size() >= 1, true);
auto dirty = dstObj->GetDirtyRanges()[0];
ASSERT_EQ(dirty.start, 5 * sizeof(Int));
ASSERT_EQ(dirty.end, 9 * sizeof(Int));
}
@@ -265,7 +272,8 @@ TEST_F(BufferTest, WriteWhileMapped) {
ASSERT_EQ(actual, expected);
auto dirty = bufObj->GetDirtyRange();
ASSERT_EQ(bufObj->GetDirtyRanges().size() >= 1, true);
auto dirty = bufObj->GetDirtyRanges()[0];
ASSERT_EQ(dirty.start, 0);
ASSERT_EQ(dirty.end, byteSize);
}
@@ -293,7 +301,8 @@ TEST_F(BufferTest, PartialUpdate) {
ASSERT_EQ(actual, expected);
auto dirty = bufObj->GetDirtyRange();
ASSERT_EQ(bufObj->GetDirtyRanges().size() >= 1, true);
auto dirty = bufObj->GetDirtyRanges()[0];
ASSERT_EQ(dirty.start, sizeof(Int));
ASSERT_EQ(dirty.end, 3 * sizeof(Int));
}
+1 -1
View File
@@ -925,7 +925,7 @@ TEST_F(ProgramTest, CompileAndLinkWithExplicitVertexIn) {
// auto& vertexSpirv = spirvs[1]; // 0 - fragment, 1 - vertex
char* pSrcVertIn = nullptr;
const char* needle = "layout(location = 2) in vec2 UV0;";
for (auto spirv: spirvs) {
for (auto spirv : spirvs) {
MG_Util::ShaderTranspiler::SpvcSession spvcSession(spirv);
spvc_compiler_options options;
spvcSession.CreateOptions(&options);
@@ -457,7 +457,10 @@ namespace MobileGL {
void *libGLES = nullptr, *libEGL = nullptr;
static const char* LibPathPrefixes[] = {
"/opt/vc/lib/", "/usr/local/lib/", "/usr/lib/", "/usr/lib/x86_64-linux-gnu/",
"/opt/vc/lib/",
"/usr/local/lib/",
"/usr/lib/",
"/usr/lib/x86_64-linux-gnu/",
"", // We should put this to the end of the list to avoid breaking `LD_LIBRARY_PATH` usage
nullptr};
static const char* LibExts[] = {"so", "so.1", "so.2", "dylib", "dll", nullptr};
@@ -531,8 +534,10 @@ namespace MobileGL {
}
MGLOG_I("OpenGL ES capabilities:");
MG_External::GLES::glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &MG_External::GLES::g_glesCaps.uniformBufferOffsetAlignment);
MGLOG_I(" GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: %d", MG_External::GLES::g_glesCaps.uniformBufferOffsetAlignment);
MG_External::GLES::glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT,
&MG_External::GLES::g_glesCaps.uniformBufferOffsetAlignment);
MGLOG_I(" GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: %d",
MG_External::GLES::g_glesCaps.uniformBufferOffsetAlignment);
}
void InitGLES() {
@@ -511,16 +511,18 @@ namespace MobileGL {
typedef EGLBoolean (*eglWaitClient_PTR)();
typedef EGLBoolean (*eglWaitGL_PTR)();
typedef EGLBoolean (*eglWaitNative_PTR)(EGLint engine);
typedef EGLSync (*eglCreateSync_PTR)(EGLDisplay dpy, EGLenum type, const EGLAttrib * attrib_list);
typedef EGLSync (*eglCreateSync_PTR)(EGLDisplay dpy, EGLenum type, const EGLAttrib* attrib_list);
typedef EGLBoolean (*eglDestroySync_PTR)(EGLDisplay dpy, EGLSync sync);
typedef EGLint (*eglClientWaitSync_PTR)(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout);
typedef EGLBoolean (*eglGetSyncAttrib_PTR)(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib * value);
typedef EGLImage (*eglCreateImage_PTR)(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib * attrib_list);
typedef EGLBoolean (*eglGetSyncAttrib_PTR)(EGLDisplay dpy, EGLSync sync, EGLint attribute,
EGLAttrib* value);
typedef EGLImage (*eglCreateImage_PTR)(EGLDisplay dpy, EGLContext ctx, EGLenum target,
EGLClientBuffer buffer, const EGLAttrib* attrib_list);
typedef EGLBoolean (*eglDestroyImage_PTR)(EGLDisplay dpy, EGLImage image);
typedef EGLSurface (*eglCreatePlatformPixmapSurface_PTR)(EGLDisplay dpy, EGLConfig config, void * native_pixmap, const EGLAttrib * attrib_list);
typedef EGLSurface (*eglCreatePlatformPixmapSurface_PTR)(EGLDisplay dpy, EGLConfig config,
void* native_pixmap, const EGLAttrib* attrib_list);
typedef EGLBoolean (*eglWaitSync_PTR)(EGLDisplay dpy, EGLSync sync, EGLint flags);
EGL_FUNC_DECL(eglBindAPI)
EGL_FUNC_DECL(eglBindTexImage)
EGL_FUNC_DECL(eglChooseConfig)
@@ -30,13 +30,22 @@ namespace MobileGL {
}
switch (attachment) {
case GL_DEPTH_ATTACHMENT:
return FramebufferAttachmentType::Depth;
case GL_STENCIL_ATTACHMENT:
return FramebufferAttachmentType::Stencil;
case GL_UNKNOWN_MGL:
default:
return FramebufferAttachmentType::Unknown;
case GL_NONE:
return FramebufferAttachmentType::None;
case GL_DEPTH_ATTACHMENT:
return FramebufferAttachmentType::Depth;
case GL_STENCIL_ATTACHMENT:
return FramebufferAttachmentType::Stencil;
case GL_FRONT_LEFT:
return FramebufferAttachmentType::FrontLeft;
case GL_FRONT_RIGHT:
return FramebufferAttachmentType::FrontRight;
case GL_BACK_LEFT:
return FramebufferAttachmentType::BackLeft;
case GL_BACK_RIGHT:
return FramebufferAttachmentType::BackRight;
default:
return FramebufferAttachmentType::Unknown;
}
}
@@ -85,7 +85,7 @@ namespace MobileGL {
case GL_PACK_SWAP_BYTES:
return PixelStoreParam::PackSwapBytes;
case GL_PACK_LSB_FIRST:
return PixelStoreParam::PackLsbFirst;
return PixelStoreParam::PackLSBFirst;
case GL_UNPACK_ALIGNMENT:
return PixelStoreParam::UnpackAlignment;
case GL_UNPACK_ROW_LENGTH:
@@ -101,7 +101,7 @@ namespace MobileGL {
case GL_UNPACK_SWAP_BYTES:
return PixelStoreParam::UnpackSwapBytes;
case GL_UNPACK_LSB_FIRST:
return PixelStoreParam::UnpackLsbFirst;
return PixelStoreParam::UnpackLSBFirst;
default:
return PixelStoreParam::Unknown;
}
@@ -234,7 +234,8 @@ namespace MobileGL {
case GL_RGBA:
return TextureInternalFormat::RGBA;
default:
MGLOG_D("%s: unknown internal format %s", __func__, MG_Util::ConvertGLEnumToString(internalformat).c_str());
MGLOG_D("%s: unknown internal format %s", __func__,
MG_Util::ConvertGLEnumToString(internalformat).c_str());
return TextureInternalFormat::Unknown;
}
}
@@ -29,12 +29,20 @@ namespace MobileGL {
}
switch (type) {
case FramebufferAttachmentType::Depth:
return GL_DEPTH_ATTACHMENT;
case FramebufferAttachmentType::Stencil:
return GL_STENCIL_ATTACHMENT;
default:
return GL_NONE;
case FramebufferAttachmentType::Depth:
return GL_DEPTH_ATTACHMENT;
case FramebufferAttachmentType::Stencil:
return GL_STENCIL_ATTACHMENT;
case FramebufferAttachmentType::FrontLeft:
return GL_FRONT_LEFT;
case FramebufferAttachmentType::FrontRight:
return GL_FRONT_RIGHT;
case FramebufferAttachmentType::BackLeft:
return GL_BACK_LEFT;
case FramebufferAttachmentType::BackRight:
return GL_BACK_RIGHT;
default:
return GL_NONE;
}
}
@@ -85,7 +85,7 @@ namespace MobileGL {
return GL_PACK_SKIP_IMAGES;
case PixelStoreParam::PackSwapBytes:
return GL_PACK_SWAP_BYTES;
case PixelStoreParam::PackLsbFirst:
case PixelStoreParam::PackLSBFirst:
return GL_PACK_LSB_FIRST;
case PixelStoreParam::UnpackAlignment:
return GL_UNPACK_ALIGNMENT;
@@ -101,7 +101,7 @@ namespace MobileGL {
return GL_UNPACK_SKIP_IMAGES;
case PixelStoreParam::UnpackSwapBytes:
return GL_UNPACK_SWAP_BYTES;
case PixelStoreParam::UnpackLsbFirst:
case PixelStoreParam::UnpackLSBFirst:
return GL_UNPACK_LSB_FIRST;
default:
return GL_UNKNOWN_MGL;
@@ -53,144 +53,263 @@ namespace MobileGL {
}
}
TextureInternalFormat ConvertInternalFormatToSized(TextureInternalFormat internalformat, TextureInputFormat format, TexturePixelDataType type) {
TextureInternalFormat ConvertInternalFormatToSized(TextureInternalFormat internalformat,
TextureInputFormat format, TexturePixelDataType type) {
switch (internalformat) {
case TextureInternalFormat::R8:
case TextureInternalFormat::R8Snorm:
case TextureInternalFormat::R16:
case TextureInternalFormat::R16Snorm:
case TextureInternalFormat::RG8:
case TextureInternalFormat::RG8Snorm:
case TextureInternalFormat::RG16:
case TextureInternalFormat::RG16Snorm:
case TextureInternalFormat::R3G3B2:
case TextureInternalFormat::RGB4:
case TextureInternalFormat::RGB5:
case TextureInternalFormat::RGB8:
case TextureInternalFormat::RGB8Snorm:
case TextureInternalFormat::RGB10:
case TextureInternalFormat::RGB12:
case TextureInternalFormat::RGB16Snorm:
case TextureInternalFormat::RGBA2:
case TextureInternalFormat::RGBA4:
case TextureInternalFormat::RGB5A1:
case TextureInternalFormat::RGBA8:
case TextureInternalFormat::RGBA8Snorm:
case TextureInternalFormat::RGB10A2:
case TextureInternalFormat::RGB10A2UI:
case TextureInternalFormat::RGBA12:
case TextureInternalFormat::RGBA16:
case TextureInternalFormat::SRGB8:
case TextureInternalFormat::SRGB8Alpha8:
case TextureInternalFormat::R16F:
case TextureInternalFormat::RG16F:
case TextureInternalFormat::RGB16F:
case TextureInternalFormat::RGBA16F:
case TextureInternalFormat::R32F:
case TextureInternalFormat::RG32F:
case TextureInternalFormat::RGB32F:
case TextureInternalFormat::RGBA32F:
case TextureInternalFormat::R11FG11FB10F:
case TextureInternalFormat::RGB9E5:
case TextureInternalFormat::R8I:
case TextureInternalFormat::R8UI:
case TextureInternalFormat::R16I:
case TextureInternalFormat::R16UI:
case TextureInternalFormat::R32I:
case TextureInternalFormat::R32UI:
case TextureInternalFormat::RG8I:
case TextureInternalFormat::RG8UI:
case TextureInternalFormat::RG16I:
case TextureInternalFormat::RG16UI:
case TextureInternalFormat::RG32I:
case TextureInternalFormat::RG32UI:
case TextureInternalFormat::RGB8I:
case TextureInternalFormat::RGB8UI:
case TextureInternalFormat::RGB16I:
case TextureInternalFormat::RGB16UI:
case TextureInternalFormat::RGB32I:
case TextureInternalFormat::RGB32UI:
case TextureInternalFormat::RGBA8I:
case TextureInternalFormat::RGBA8UI:
case TextureInternalFormat::RGBA16I:
case TextureInternalFormat::RGBA16UI:
case TextureInternalFormat::RGBA32I:
case TextureInternalFormat::RGBA32UI:
case TextureInternalFormat::DepthComponent16:
case TextureInternalFormat::DepthComponent24:
case TextureInternalFormat::DepthComponent32: // not a standard format in OpenGL core profile
case TextureInternalFormat::DepthComponent32F:
case TextureInternalFormat::Depth24Stencil8:
case TextureInternalFormat::Depth32FStencil8:
return internalformat;
// probably we should assume unorm here?
case TextureInternalFormat::RGBA: {
switch (type) {
case TexturePixelDataType::UnsignedByte:
return TextureInternalFormat::RGBA8;
case TexturePixelDataType::UnsignedShort:
return TextureInternalFormat::RGBA16;
default:
MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, returning original.",
__func__,
MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(),
MG_Util::ConvertTextureInputFormatToString(format).c_str(),
MG_Util::ConvertTexturePixelDataTypeToString(type).c_str());
return internalformat;
}
}
case TextureInternalFormat::RGB: {
switch (type) {
case TexturePixelDataType::UnsignedByte:
return TextureInternalFormat::RGB8;
default:
MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, returning original.",
__func__,
MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(),
MG_Util::ConvertTextureInputFormatToString(format).c_str(),
MG_Util::ConvertTexturePixelDataTypeToString(type).c_str());
return internalformat;
}
}
case TextureInternalFormat::RG: {
switch (type) {
case TexturePixelDataType::UnsignedByte:
return TextureInternalFormat::RG8;
case TexturePixelDataType::UnsignedShort:
return TextureInternalFormat::RG16;
default:
MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, returning original.",
__func__,
MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(),
MG_Util::ConvertTextureInputFormatToString(format).c_str(),
MG_Util::ConvertTexturePixelDataTypeToString(type).c_str());
return internalformat;
}
}
case TextureInternalFormat::Red: {
switch (type) {
case TexturePixelDataType::UnsignedByte:
return TextureInternalFormat::R8;
case TexturePixelDataType::UnsignedShort:
return TextureInternalFormat::R16;
default:
MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, returning original.",
__func__,
MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(),
MG_Util::ConvertTextureInputFormatToString(format).c_str(),
MG_Util::ConvertTexturePixelDataTypeToString(type).c_str());
return internalformat;
}
}
default: {
MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, returning original.",
__func__,
MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(),
case TextureInternalFormat::R8:
case TextureInternalFormat::R8Snorm:
case TextureInternalFormat::R16:
case TextureInternalFormat::R16Snorm:
case TextureInternalFormat::RG8:
case TextureInternalFormat::RG8Snorm:
case TextureInternalFormat::RG16:
case TextureInternalFormat::RG16Snorm:
case TextureInternalFormat::R3G3B2:
case TextureInternalFormat::RGB4:
case TextureInternalFormat::RGB5:
case TextureInternalFormat::RGB8:
case TextureInternalFormat::RGB8Snorm:
case TextureInternalFormat::RGB10:
case TextureInternalFormat::RGB12:
case TextureInternalFormat::RGB16Snorm:
case TextureInternalFormat::RGBA2:
case TextureInternalFormat::RGBA4:
case TextureInternalFormat::RGB5A1:
case TextureInternalFormat::RGBA8:
case TextureInternalFormat::RGBA8Snorm:
case TextureInternalFormat::RGB10A2:
case TextureInternalFormat::RGB10A2UI:
case TextureInternalFormat::RGBA12:
case TextureInternalFormat::RGBA16:
case TextureInternalFormat::SRGB8:
case TextureInternalFormat::SRGB8Alpha8:
case TextureInternalFormat::R16F:
case TextureInternalFormat::RG16F:
case TextureInternalFormat::RGB16F:
case TextureInternalFormat::RGBA16F:
case TextureInternalFormat::R32F:
case TextureInternalFormat::RG32F:
case TextureInternalFormat::RGB32F:
case TextureInternalFormat::RGBA32F:
case TextureInternalFormat::R11FG11FB10F:
case TextureInternalFormat::RGB9E5:
case TextureInternalFormat::R8I:
case TextureInternalFormat::R8UI:
case TextureInternalFormat::R16I:
case TextureInternalFormat::R16UI:
case TextureInternalFormat::R32I:
case TextureInternalFormat::R32UI:
case TextureInternalFormat::RG8I:
case TextureInternalFormat::RG8UI:
case TextureInternalFormat::RG16I:
case TextureInternalFormat::RG16UI:
case TextureInternalFormat::RG32I:
case TextureInternalFormat::RG32UI:
case TextureInternalFormat::RGB8I:
case TextureInternalFormat::RGB8UI:
case TextureInternalFormat::RGB16I:
case TextureInternalFormat::RGB16UI:
case TextureInternalFormat::RGB32I:
case TextureInternalFormat::RGB32UI:
case TextureInternalFormat::RGBA8I:
case TextureInternalFormat::RGBA8UI:
case TextureInternalFormat::RGBA16I:
case TextureInternalFormat::RGBA16UI:
case TextureInternalFormat::RGBA32I:
case TextureInternalFormat::RGBA32UI:
case TextureInternalFormat::DepthComponent16:
case TextureInternalFormat::DepthComponent24:
case TextureInternalFormat::DepthComponent32: // not a standard format in OpenGL core profile
case TextureInternalFormat::DepthComponent32F:
case TextureInternalFormat::Depth24Stencil8:
case TextureInternalFormat::Depth32FStencil8:
return internalformat;
// probably we should assume unorm here?
case TextureInternalFormat::RGBA: {
switch (type) {
case TexturePixelDataType::UnsignedByte:
return TextureInternalFormat::RGBA8;
case TexturePixelDataType::UnsignedShort:
return TextureInternalFormat::RGBA16;
default:
MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, "
"returning original.",
__func__, MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(),
MG_Util::ConvertTextureInputFormatToString(format).c_str(),
MG_Util::ConvertTexturePixelDataTypeToString(type).c_str());
return internalformat;
}
}
case TextureInternalFormat::RGB: {
switch (type) {
case TexturePixelDataType::UnsignedByte:
return TextureInternalFormat::RGB8;
default:
MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, "
"returning original.",
__func__, MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(),
MG_Util::ConvertTextureInputFormatToString(format).c_str(),
MG_Util::ConvertTexturePixelDataTypeToString(type).c_str());
return internalformat;
}
}
case TextureInternalFormat::RG: {
switch (type) {
case TexturePixelDataType::UnsignedByte:
return TextureInternalFormat::RG8;
case TexturePixelDataType::UnsignedShort:
return TextureInternalFormat::RG16;
default:
MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, "
"returning original.",
__func__, MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(),
MG_Util::ConvertTextureInputFormatToString(format).c_str(),
MG_Util::ConvertTexturePixelDataTypeToString(type).c_str());
return internalformat;
}
}
case TextureInternalFormat::Red: {
switch (type) {
case TexturePixelDataType::UnsignedByte:
return TextureInternalFormat::R8;
case TexturePixelDataType::UnsignedShort:
return TextureInternalFormat::R16;
default:
MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, "
"returning original.",
__func__, MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(),
MG_Util::ConvertTextureInputFormatToString(format).c_str(),
MG_Util::ConvertTexturePixelDataTypeToString(type).c_str());
return internalformat;
}
}
case TextureInternalFormat::DepthComponent: {
switch (type) {
case TexturePixelDataType::UnsignedShort:
return TextureInternalFormat::DepthComponent16;
case TexturePixelDataType::UnsignedInt:
return TextureInternalFormat::DepthComponent32;
case TexturePixelDataType::Float:
return TextureInternalFormat::DepthComponent32F;
default:
MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, "
"returning original.",
__func__, MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(),
MG_Util::ConvertTextureInputFormatToString(format).c_str(),
MG_Util::ConvertTexturePixelDataTypeToString(type).c_str());
return internalformat;
}
}
case TextureInternalFormat::DepthStencil: {
switch (type) {
case TexturePixelDataType::UnsignedInt248:
return TextureInternalFormat::Depth24Stencil8;
default:
MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, "
"returning original.",
__func__, MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(),
MG_Util::ConvertTextureInputFormatToString(format).c_str(),
MG_Util::ConvertTexturePixelDataTypeToString(type).c_str());
return internalformat;
}
}
default: {
MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, returning "
"original.",
__func__, MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(),
MG_Util::ConvertTextureInputFormatToString(format).c_str(),
MG_Util::ConvertTexturePixelDataTypeToString(type).c_str());
return internalformat;
}
}
}
TextureInternalFormat ConvertInternalFormatToUnsized(TextureInternalFormat internalformat) {
switch (internalformat) {
case TextureInternalFormat::R8:
case TextureInternalFormat::R8Snorm:
case TextureInternalFormat::R16:
case TextureInternalFormat::R16Snorm:
case TextureInternalFormat::R16F:
case TextureInternalFormat::R32F:
case TextureInternalFormat::R8I:
case TextureInternalFormat::R8UI:
case TextureInternalFormat::R16I:
case TextureInternalFormat::R16UI:
case TextureInternalFormat::R32I:
case TextureInternalFormat::R32UI:
case TextureInternalFormat::Red:
return TextureInternalFormat::Red;
case TextureInternalFormat::RG8:
case TextureInternalFormat::RG8Snorm:
case TextureInternalFormat::RG16:
case TextureInternalFormat::RG16Snorm:
case TextureInternalFormat::RG16F:
case TextureInternalFormat::RG32F:
case TextureInternalFormat::RG8I:
case TextureInternalFormat::RG8UI:
case TextureInternalFormat::RG16I:
case TextureInternalFormat::RG16UI:
case TextureInternalFormat::RG32I:
case TextureInternalFormat::RG32UI:
case TextureInternalFormat::RG:
return TextureInternalFormat::RG;
case TextureInternalFormat::R3G3B2:
case TextureInternalFormat::RGB4:
case TextureInternalFormat::RGB5:
case TextureInternalFormat::RGB8:
case TextureInternalFormat::RGB8Snorm:
case TextureInternalFormat::RGB10:
case TextureInternalFormat::RGB12:
case TextureInternalFormat::RGB16Snorm:
case TextureInternalFormat::RGB16F:
case TextureInternalFormat::RGB32F:
case TextureInternalFormat::R11FG11FB10F:
case TextureInternalFormat::RGB9E5:
case TextureInternalFormat::SRGB8:
case TextureInternalFormat::RGB8I:
case TextureInternalFormat::RGB8UI:
case TextureInternalFormat::RGB16I:
case TextureInternalFormat::RGB16UI:
case TextureInternalFormat::RGB32I:
case TextureInternalFormat::RGB32UI:
case TextureInternalFormat::RGB:
return TextureInternalFormat::RGB;
case TextureInternalFormat::RGBA2:
case TextureInternalFormat::RGBA4:
case TextureInternalFormat::RGB5A1:
case TextureInternalFormat::RGBA8:
case TextureInternalFormat::RGBA8Snorm:
case TextureInternalFormat::RGB10A2:
case TextureInternalFormat::RGB10A2UI:
case TextureInternalFormat::RGBA12:
case TextureInternalFormat::RGBA16:
case TextureInternalFormat::SRGB8Alpha8:
case TextureInternalFormat::RGBA16F:
case TextureInternalFormat::RGBA32F:
case TextureInternalFormat::RGBA8I:
case TextureInternalFormat::RGBA8UI:
case TextureInternalFormat::RGBA16I:
case TextureInternalFormat::RGBA16UI:
case TextureInternalFormat::RGBA32I:
case TextureInternalFormat::RGBA32UI:
case TextureInternalFormat::RGBA:
return TextureInternalFormat::RGBA;
case TextureInternalFormat::DepthComponent16:
case TextureInternalFormat::DepthComponent24:
case TextureInternalFormat::DepthComponent32:
case TextureInternalFormat::DepthComponent32F:
case TextureInternalFormat::DepthComponent:
return TextureInternalFormat::DepthComponent;
case TextureInternalFormat::Depth24Stencil8:
case TextureInternalFormat::Depth32FStencil8:
case TextureInternalFormat::DepthStencil:
return TextureInternalFormat::DepthStencil;
default:
MGLOG_W("%s: Unknown or unhandled internal format %s, returning original.", __func__,
MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str());
return internalformat;
}
}
} // namespace MG_Util
} // namespace MobileGL
@@ -13,6 +13,8 @@
namespace MobileGL {
namespace MG_Util {
TextureTarget ConvertTextureUploadTargetToTextureTarget(TextureUploadTarget target);
TextureInternalFormat ConvertInternalFormatToSized(TextureInternalFormat internalformat, TextureInputFormat format, TexturePixelDataType type);
TextureInternalFormat ConvertInternalFormatToSized(TextureInternalFormat internalformat,
TextureInputFormat format, TexturePixelDataType type);
TextureInternalFormat ConvertInternalFormatToUnsized(TextureInternalFormat internalformat);
} // namespace MG_Util
} // namespace MobileGL
@@ -84,8 +84,8 @@ namespace MobileGL {
return "PackSkipImages";
case PixelStoreParam::PackSwapBytes:
return "PackSwapBytes";
case PixelStoreParam::PackLsbFirst:
return "PackLsbFirst";
case PixelStoreParam::PackLSBFirst:
return "PackLSBFirst";
case PixelStoreParam::UnpackAlignment:
return "UnpackAlignment";
case PixelStoreParam::UnpackRowLength:
@@ -100,8 +100,8 @@ namespace MobileGL {
return "UnpackSkipImages";
case PixelStoreParam::UnpackSwapBytes:
return "UnpackSwapBytes";
case PixelStoreParam::UnpackLsbFirst:
return "UnpackLsbFirst";
case PixelStoreParam::UnpackLSBFirst:
return "UnpackLSBFirst";
default:
return "Unknown";
}
+2 -2
View File
@@ -91,9 +91,9 @@ namespace MobileGL {
int n = std::vsnprintf(buffer, sizeof(buffer), fmt, args);
std::string out = header +
#if MOBILEGL_LOG_ENABLE_STACKTRACE
padding +
padding +
#endif
std::string(buffer, n) + "\n";
std::string(buffer, n) + "\n";
#if MOBILEGL_LOG_ENABLE_CONSOLE
std::fwrite(out.c_str(), 1, out.size(), stdout);
+134
View File
@@ -0,0 +1,134 @@
// MobileGL - MobileGL/MG_Util/Math/VectorTypes.cpp
// Copyright (c) 2025-2026 MobileGL-Dev
// Licensed under the GNU Lesser General Public License v3.0:
// https://www.gnu.org/licenses/gpl-3.0.txt
// https://www.gnu.org/licenses/lgpl-3.0.txt
// SPDX-License-Identifier: LGPL-3.0-only
// End of Source File Header
#include "VectorTypes.h"
namespace MobileGL {
void VecRange1D::Add(const Range1D& newRange, Double ratio, SizeT* outMinStart, SizeT* outMaxEnd) {
if (this->empty()) {
this->push_back(newRange);
m_overallMaxEnd = newRange.end;
if (outMinStart) *outMinStart = this->front().start;
if (outMaxEnd) *outMaxEnd = m_overallMaxEnd;
return;
}
auto it = std::lower_bound(this->begin(), this->end(), newRange.start,
[](const Range1D& a, SizeT valueStart) { return a.start < valueStart; });
size_t pos = static_cast<size_t>(std::distance(this->begin(), it));
auto calc_gap = [](const Range1D& a, const Range1D& b) -> SizeT {
return (b.start > a.end) ? (b.start - a.end) : 0;
};
auto calc_threshold = [ratio](const Range1D& a, const Range1D& b) -> SizeT {
SizeT minStart = (a.start < b.start) ? a.start : b.start;
SizeT maxEnd = (a.end > b.end) ? a.end : b.end;
SizeT span = (maxEnd > minStart) ? (maxEnd - minStart) : 0;
return static_cast<SizeT>(static_cast<Double>(span) * ratio);
};
if (pos >= this->size()) {
Range1D& last = this->back();
SizeT gap = calc_gap(last, newRange);
SizeT threshold = calc_threshold(last, newRange);
if (gap <= threshold) {
last.end = std::max(last.end, newRange.end);
m_overallMaxEnd = std::max(m_overallMaxEnd, last.end);
} else {
this->push_back(newRange);
m_overallMaxEnd = std::max(m_overallMaxEnd, newRange.end);
}
if (outMinStart) *outMinStart = this->front().start;
if (outMaxEnd) *outMaxEnd = m_overallMaxEnd;
return;
}
bool merged = false;
if (pos > 0) {
Range1D& prev = (*this)[pos - 1];
SizeT gapPrev = calc_gap(prev, newRange);
SizeT thresholdPrev = calc_threshold(prev, newRange);
if (gapPrev <= thresholdPrev) {
prev.end = std::max(prev.end, newRange.end);
m_overallMaxEnd = std::max(m_overallMaxEnd, prev.end);
size_t writeIdx = pos - 1;
while (writeIdx + 1 < this->size()) {
Range1D& cur = (*this)[writeIdx];
Range1D& nxt = (*this)[writeIdx + 1];
SizeT gap = calc_gap(cur, nxt);
SizeT threshold = calc_threshold(cur, nxt);
if (gap <= threshold) {
// merge nxt into cur
cur.end = std::max(cur.end, nxt.end);
this->erase(this->begin() + (writeIdx + 1));
m_overallMaxEnd = std::max(m_overallMaxEnd, cur.end);
} else {
break;
}
}
merged = true;
}
}
if (!merged) {
// Try to merge with the current pos interval or insert
Range1D& cur = (*this)[pos];
SizeT gapCur = calc_gap(newRange, cur); // gap between new and cur
SizeT thresholdCur = calc_threshold(newRange, cur);
if (gapCur <= thresholdCur) {
cur.start = std::min(cur.start, newRange.start);
cur.end = std::max(cur.end, newRange.end);
m_overallMaxEnd = std::max(m_overallMaxEnd, cur.end);
size_t writeIdx = pos;
while (writeIdx + 1 < this->size()) {
Range1D& cur2 = (*this)[writeIdx];
Range1D& nxt = (*this)[writeIdx + 1];
SizeT gap = calc_gap(cur2, nxt);
SizeT threshold = calc_threshold(cur2, nxt);
if (gap <= threshold) {
cur2.end = std::max(cur2.end, nxt.end);
this->erase(this->begin() + (writeIdx + 1));
m_overallMaxEnd = std::max(m_overallMaxEnd, cur2.end);
} else {
break;
}
}
merged = true;
} else {
this->insert(this->begin() + pos, newRange);
m_overallMaxEnd = std::max(m_overallMaxEnd, newRange.end);
merged = true;
}
}
if (outMinStart) {
*outMinStart = this->front().start;
}
if (outMaxEnd) {
*outMaxEnd = m_overallMaxEnd;
}
}
SizeT VecRange1D::GetOverallMaxEnd() const {
return m_overallMaxEnd;
}
SizeT VecRange1D::GetOverallMinStart() const {
if (this->empty()) return 0;
return this->front().start;
}
} // namespace MobileGL
+11 -1
View File
@@ -11,7 +11,6 @@
#include <Includes.h>
namespace MobileGL {
template <typename Derived, typename T, SizeT N>
struct VecBase {
Array<T, N> data;
@@ -247,4 +246,15 @@ namespace MobileGL {
return incident - normal * (2.0f * incident.Dot(normal));
}
} // namespace MG_Util
class VecRange1D : public Vector<Range1D> {
public:
void Add(const Range1D& newRange, Double ratio = 0.07, SizeT* outMinStart = nullptr,
SizeT* outMaxEnd = nullptr);
SizeT GetOverallMaxEnd() const;
SizeT GetOverallMinStart() const;
private:
SizeT m_overallMaxEnd;
};
} // namespace MobileGL
@@ -227,15 +227,17 @@ namespace MobileGL {
return allSpirv;
}
bool ShaderCompiler::SanitizeAndOptimizeBinary(const Vector<Uint32>& inputBinary, Vector<uint32_t>& outputBinary) {
bool ShaderCompiler::SanitizeAndOptimizeBinary(const Vector<Uint32>& inputBinary,
Vector<uint32_t>& outputBinary) {
using namespace spvtools;
OptimizerOptions options;
options.set_run_validator(false);
Optimizer optimizer(SPV_ENV_UNIVERSAL_1_5);
optimizer
.RegisterPass(EliminateFloatEqualsZeroPass::CreateEliminateFloatEqualsZeroPass())
;
optimizer.RegisterPass(EliminateFloatEqualsZeroPass::CreateEliminateFloatEqualsZeroPass());
return optimizer.Run(inputBinary.data(), inputBinary.size(), &outputBinary);
return optimizer.Run(inputBinary.data(), inputBinary.size(), &outputBinary, options);
}
Result<String> ShaderCompiler::DecompileShader(SpvcSession& session) {
@@ -20,7 +20,8 @@ namespace MobileGL {
static Result<SharedPtr<glslang::TShader>> CompileShader(const ShaderAttrib& attrib);
static Result<SharedPtr<glslang::TProgram>> LinkProgram(const ProgramAttrib& attrib);
static Result<Vector<Vector<unsigned>>> GetSpirvBinaryFromProgram(const ProgramBinaryAttrib& attrib);
static bool SanitizeAndOptimizeBinary(const Vector<Uint32>& inputBinary, Vector<uint32_t>& outputBinary);
static bool SanitizeAndOptimizeBinary(const Vector<Uint32>& inputBinary,
Vector<uint32_t>& outputBinary);
static Result<String> DecompileShader(SpvcSession& session);
};
} // namespace ShaderTranspiler
@@ -1,4 +1,4 @@
// MobileGL - MobileGL/MG_Util/ShaderTranspiler/FloatEqualsZeroEliminationPass.cpp
// MobileGL - MobileGL/MG_Util/ShaderTranspiler/SpirvPasses/EliminateFloatEqualsZeroPass.cpp
// Copyright (c) 2025-2026 MobileGL-Dev
// Licensed under the GNU Lesser General Public License v3.0:
// https://www.gnu.org/licenses/gpl-3.0.txt
@@ -39,7 +39,7 @@ namespace MobileGL {
// 3. iterate all function -> basic block -> insn
for (auto& func : *get_module()) {
for (auto& bb : func) {
for (auto itInst = bb.begin(); itInst != bb.end(); ) {
for (auto itInst = bb.begin(); itInst != bb.end();) {
auto& inst = *itInst;
bool shouldSkip = true;
@@ -48,14 +48,14 @@ namespace MobileGL {
// `OpFOrdNotEqual` or `OpFUnordNotEqual`,
// simply skip if irrelevant
switch (inst.opcode()) {
case spv::Op::OpFOrdEqual:
case spv::Op::OpFUnordEqual:
case spv::Op::OpFOrdNotEqual:
case spv::Op::OpFUnordNotEqual:
shouldSkip = false;
break;
default:
break;
case spv::Op::OpFOrdEqual:
case spv::Op::OpFUnordEqual:
case spv::Op::OpFOrdNotEqual:
case spv::Op::OpFUnordNotEqual:
shouldSkip = false;
break;
default:
break;
}
if (shouldSkip) {
@@ -96,18 +96,13 @@ namespace MobileGL {
// 2. Create constant ID for `Epsilon`
const analysis::Constant* eps_const = const_mgr->GetConstant(
type_mgr->GetType(float_type_id),
{*(reinterpret_cast<const uint32_t*>(&K_EPSILON))}
);
type_mgr->GetType(float_type_id), {*(reinterpret_cast<const uint32_t*>(&K_EPSILON))});
uint32_t eps_id = const_mgr->GetDefiningInstruction(eps_const)->result_id();
// 3. Build Abs(x) inst
// OpExtInst %float_type %glsl_import Abs %x
InstructionBuilder builder(
context(),
&inst,
IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping
);
context(), &inst, IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
std::vector<Operand> abs_operands;
abs_operands.push_back({SPV_OPERAND_TYPE_ID, {glsl_std_450_id}});
@@ -117,12 +112,7 @@ namespace MobileGL {
// In GLSL.std.450, `FAbs`'s OpCode == 4
// Ref: https://registry.khronos.org/SPIR-V/specs/1.0/GLSL.std.450.html
Instruction* abs_inst = builder.AddInstruction(MakeUnique<Instruction>(
context(),
spv::Op::OpExtInst,
float_type_id,
context()->TakeNextId(),
abs_operands
));
context(), spv::Op::OpExtInst, float_type_id, context()->TakeNextId(), abs_operands));
// 4. build Abs(x) < Epsilon
// OpFOrdLessThan %bool_type %abs_val %eps
@@ -130,14 +120,11 @@ namespace MobileGL {
less_operands.push_back({SPV_OPERAND_TYPE_ID, {abs_inst->result_id()}});
less_operands.push_back({SPV_OPERAND_TYPE_ID, {eps_id}});
bool isEqualOp = (inst.opcode() == spv::Op::OpFOrdEqual || inst.opcode() == spv::Op::OpFUnordEqual);
bool isEqualOp =
(inst.opcode() == spv::Op::OpFOrdEqual || inst.opcode() == spv::Op::OpFUnordEqual);
Instruction* less_than_inst = builder.AddInstruction(MakeUnique<Instruction>(
context(),
isEqualOp ? spv::Op::OpFOrdLessThan : spv::Op::OpFOrdGreaterThanEqual,
bool_type_id,
context()->TakeNextId(),
less_operands
));
context(), isEqualOp ? spv::Op::OpFOrdLessThan : spv::Op::OpFOrdGreaterThanEqual,
bool_type_id, context()->TakeNextId(), less_operands));
// 5. Replaces all uses of old insn with new one
context()->ReplaceAllUsesWith(inst.result_id(), less_than_inst->result_id());
@@ -161,5 +148,5 @@ namespace MobileGL {
return spvtools::Optimizer::PassToken(MakeUnique<EliminateFloatEqualsZeroPass>());
}
} // namespace ShaderTranspiler
}
}
} // namespace MG_Util
} // namespace MobileGL
@@ -1,4 +1,4 @@
// MobileGL - MobileGL/MG_Util/ShaderTranspiler/FloatEqualsZeroEliminationPass.h
// MobileGL - MobileGL/MG_Util/ShaderTranspiler/SpirvPasses/EliminateFloatEqualsZeroPass.h
// Copyright (c) 2025-2026 MobileGL-Dev
// Licensed under the GNU Lesser General Public License v3.0:
// https://www.gnu.org/licenses/gpl-3.0.txt
@@ -15,16 +15,16 @@
namespace MobileGL {
namespace MG_Util {
namespace ShaderTranspiler {
class EliminateFloatEqualsZeroPass: public spvtools::opt::Pass {
class EliminateFloatEqualsZeroPass : public spvtools::opt::Pass {
public:
const char* name() const override { return "float-equals-zero-elimination"; }
Status Process() override;
static spvtools::Optimizer::PassToken CreateEliminateFloatEqualsZeroPass();
private:
const float K_EPSILON = 0.0001f;
};
} // namespace ShaderTranspiler
} // namespace MG_Util
} // namespace MobileGL
@@ -108,8 +108,8 @@ namespace MobileGL::MG_Util::PixelStoreProcessor {
const Int copyHeight = height;
const Int copyDepth = depth;
MGLOG_D("%s: start at: (%d, %d, %d), copy size: (%d, %d, %d), i/o row stride: (%d, %dx%d)", __func__,
startX, startY, startZ, copyWidth, copyHeight, copyDepth, inputRowStride, width, pixelSize);
MGLOG_D("%s: start at: (%d, %d, %d), copy size: (%d, %d, %d), i/o row stride: (%d, %dx%d)", __func__, startX,
startY, startZ, copyWidth, copyHeight, copyDepth, inputRowStride, width, pixelSize);
if (copyWidth <= 0 || copyHeight <= 0 || copyDepth <= 0) {
outSize = 0;
@@ -152,14 +152,14 @@ namespace MobileGL::MG_Util::PixelStoreProcessor {
if (textureInputFormat == TextureInputFormat::BGRA &&
targetInternalFormat == TextureInternalFormat::RGBA8) {
MGLOG_D("%s: Swizzle (BGRA)", __func__);
// MGLOG_D("%s: pixel0 before = %x", __func__, *((Uint32*)layerDst));
// MGLOG_D("%s: pixel0 before = %x", __func__, *((Uint32*)layerDst));
ProcessColorSwizzle(layerDst, static_cast<SizeT>(copyWidth),
{TextureSwizzleParam::Green, TextureSwizzleParam::Blue,
TextureSwizzleParam::Alpha, TextureSwizzleParam::Red});
// MGLOG_D("%s: pixel0 after = %x", __func__, *((Uint32*)layerDst));
// MGLOG_D("%s: pixel0 after = %x", __func__, *((Uint32*)layerDst));
}
// else
// MGLOG_D("%s: pixel0 = %x", __func__, *((Uint32*)layerDst));
// else
// MGLOG_D("%s: pixel0 = %x", __func__, *((Uint32*)layerDst));
layerSrc += inputRowStride;
layerDst += outputRowStride;
@@ -14,7 +14,8 @@
namespace MobileGL::MG_Util::PixelStoreProcessor {
void* ProcessTexturePixelsDataUnpack(const void* inputPixels, const PixelStoreParameters& params,
TextureInternalFormat targetInternalFormat, TextureInputFormat textureInputFormat, TexturePixelDataType inputDataType,
TextureInternalFormat targetInternalFormat,
TextureInputFormat textureInputFormat, TexturePixelDataType inputDataType,
IntVec3 dimension, Bool isBitmap, SizeT& outSize);
void* ProcessTexturePixelsDataPack(const void* inputPixels, const PixelStoreParameters& params, SizeT pixelSize,
IntVec3 dimension, Bool isBitmap, SizeT& outSize);
@@ -10,335 +10,338 @@
#include "MG_Util/Converters/GLToStr/GLEnumConverter.h"
namespace MobileGL::MG_Util::TextureFormatProcessor {
void NormalizePixelFormat(GLenum internalFormat, Flags<PixelFormatNormalizeOptionBit> options, GLenum* outInternalFormat, GLenum* outFormat, GLenum* outType) {
void NormalizePixelFormat(GLenum internalFormat, Flags<PixelFormatNormalizeOptionBit> options,
GLenum* outInternalFormat, GLenum* outFormat, GLenum* outType) {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
// internal format
if (outInternalFormat) {
switch (internalFormat) {
case GL_DEPTH_COMPONENT32:
*outInternalFormat = GL_DEPTH_COMPONENT;
case GL_DEPTH_COMPONENT32:
*outInternalFormat = GL_DEPTH_COMPONENT;
break;
case GL_RGBA16:
if (options & PixelFormatNormalizeOptionBit::NoNorm16) {
*outInternalFormat = GL_RGBA32F;
break;
case GL_RGBA16:
if (options & PixelFormatNormalizeOptionBit::NoNorm16) {
*outInternalFormat = GL_RGBA32F;
break;
}
case GL_RGB16:
if (options & PixelFormatNormalizeOptionBit::NoNorm16) {
*outInternalFormat = GL_RGB32F;
break;
}
case GL_RG16:
if (options & PixelFormatNormalizeOptionBit::NoNorm16) {
*outInternalFormat = GL_RG32F;
break;
}
case GL_R16:
if (options & PixelFormatNormalizeOptionBit::NoNorm16) {
*outInternalFormat = GL_R32F;
break;
}
default:
*outInternalFormat = internalFormat;
}
case GL_RGB16:
if (options & PixelFormatNormalizeOptionBit::NoNorm16) {
*outInternalFormat = GL_RGB32F;
break;
}
case GL_RG16:
if (options & PixelFormatNormalizeOptionBit::NoNorm16) {
*outInternalFormat = GL_RG32F;
break;
}
case GL_R16:
if (options & PixelFormatNormalizeOptionBit::NoNorm16) {
*outInternalFormat = GL_R32F;
break;
}
default:
*outInternalFormat = internalFormat;
break;
}
}
// format
if (outFormat) {
switch (internalFormat) {
// Color Unsigned Normalized
case GL_RGBA:
case GL_RGBA16:
case GL_RGBA8:
// Color Unsigned Normalized
case GL_RGBA:
case GL_RGBA16:
case GL_RGBA8:
*outFormat = GL_RGBA;
break;
case GL_RGB:
case GL_RGB16:
case GL_RGB8:
*outFormat = GL_RGB;
break;
case GL_RG:
case GL_RG16:
case GL_RG8:
*outFormat = GL_RG;
break;
case GL_RED:
case GL_R16:
case GL_R8:
*outFormat = GL_RED;
break;
// Color Signed Normalized
case GL_RGBA_SNORM:
case GL_RGBA16_SNORM:
case GL_RGBA8_SNORM:
*outFormat = GL_RGBA;
break;
case GL_RGB_SNORM:
case GL_RGB16_SNORM:
case GL_RGB8_SNORM:
*outFormat = GL_RGB;
break;
case GL_RG_SNORM:
case GL_RG16_SNORM:
case GL_RG8_SNORM:
*outFormat = GL_RG;
break;
case GL_RED_SNORM:
case GL_R16_SNORM:
case GL_R8_SNORM:
*outFormat = GL_RED;
break;
// Color Integer
case GL_RGBA32UI:
case GL_RGBA16UI:
case GL_RGBA8UI:
case GL_RGBA32I:
case GL_RGBA16I:
case GL_RGBA8I:
*outFormat = GL_RGBA_INTEGER;
break;
case GL_RGB32UI:
case GL_RGB16UI:
case GL_RGB8UI:
case GL_RGB32I:
case GL_RGB16I:
case GL_RGB8I:
*outFormat = GL_RGB_INTEGER;
break;
case GL_RG32UI:
case GL_RG16UI:
case GL_RG8UI:
case GL_RG32I:
case GL_RG16I:
case GL_RG8I:
*outFormat = GL_RG_INTEGER;
break;
case GL_R32UI:
case GL_R16UI:
case GL_R8UI:
case GL_R32I:
case GL_R16I:
case GL_R8I:
*outFormat = GL_RED_INTEGER;
break;
// Color Float
case GL_RGBA32F:
case GL_RGBA16F:
*outFormat = GL_RGBA;
break;
case GL_RGB32F:
case GL_RGB16F:
*outFormat = GL_RGB;
break;
case GL_RG32F:
case GL_RG16F:
*outFormat = GL_RG;
break;
case GL_R32F:
case GL_R16F:
*outFormat = GL_RED;
break;
// Color sRGB
case GL_SRGB:
case GL_SRGB8:
*outFormat = GL_RGB;
break;
// Color sized other
case GL_RGB9_E5:
case GL_R11F_G11F_B10F:
*outFormat = GL_RGB;
break;
case GL_RGB10_A2:
case GL_RGB5_A1:
*outFormat = GL_RGBA;
break;
// Depth
case GL_DEPTH_COMPONENT16:
case GL_DEPTH_COMPONENT24:
case GL_DEPTH_COMPONENT32:
case GL_DEPTH_COMPONENT32F:
case GL_DEPTH_COMPONENT:
*outFormat = GL_DEPTH_COMPONENT;
break;
// Depth Stencil
case GL_DEPTH32F_STENCIL8:
case GL_DEPTH_STENCIL:
*outFormat = GL_DEPTH_STENCIL;
break;
default:
MGLOG_E("NormalizePixelFormat: outFormat: unhandled internalFormat: %s",
MG_Util::ConvertGLEnumToString(internalFormat).c_str());
// Fallback handling for other formats
// Try to infer format from internal format name
if (strstr(MG_Util::ConvertGLEnumToString(internalFormat).c_str(), "RGBA") != nullptr) {
*outFormat = GL_RGBA;
break;
case GL_RGB:
case GL_RGB16:
case GL_RGB8:
} else if (strstr(MG_Util::ConvertGLEnumToString(internalFormat).c_str(), "RGB") != nullptr) {
*outFormat = GL_RGB;
break;
case GL_RG:
case GL_RG16:
case GL_RG8:
} else if (strstr(MG_Util::ConvertGLEnumToString(internalFormat).c_str(), "RG") != nullptr) {
*outFormat = GL_RG;
break;
case GL_RED:
case GL_R16:
case GL_R8:
} else if (strstr(MG_Util::ConvertGLEnumToString(internalFormat).c_str(), "RED") != nullptr) {
*outFormat = GL_RED;
break;
// Color Signed Normalized
case GL_RGBA_SNORM:
case GL_RGBA16_SNORM:
case GL_RGBA8_SNORM:
*outFormat = GL_RGBA;
break;
case GL_RGB_SNORM:
case GL_RGB16_SNORM:
case GL_RGB8_SNORM:
*outFormat = GL_RGB;
break;
case GL_RG_SNORM:
case GL_RG16_SNORM:
case GL_RG8_SNORM:
*outFormat = GL_RG;
break;
case GL_RED_SNORM:
case GL_R16_SNORM:
case GL_R8_SNORM:
*outFormat = GL_RED;
break;
// Color Integer
case GL_RGBA32UI:
case GL_RGBA16UI:
case GL_RGBA8UI:
case GL_RGBA32I:
case GL_RGBA16I:
case GL_RGBA8I:
*outFormat = GL_RGBA_INTEGER;
break;
case GL_RGB32UI:
case GL_RGB16UI:
case GL_RGB8UI:
case GL_RGB32I:
case GL_RGB16I:
case GL_RGB8I:
*outFormat = GL_RGB_INTEGER;
break;
case GL_RG32UI:
case GL_RG16UI:
case GL_RG8UI:
case GL_RG32I:
case GL_RG16I:
case GL_RG8I:
*outFormat = GL_RG_INTEGER;
break;
case GL_R32UI:
case GL_R16UI:
case GL_R8UI:
case GL_R32I:
case GL_R16I:
case GL_R8I:
*outFormat = GL_RED_INTEGER;
break;
// Color Float
case GL_RGBA32F:
case GL_RGBA16F:
*outFormat = GL_RGBA;
break;
case GL_RGB32F:
case GL_RGB16F:
*outFormat = GL_RGB;
break;
case GL_RG32F:
case GL_RG16F:
*outFormat = GL_RG;
break;
case GL_R32F:
case GL_R16F:
*outFormat = GL_RED;
break;
// Color sRGB
case GL_SRGB:
case GL_SRGB8:
*outFormat = GL_RGB;
break;
// Color sized other
case GL_RGB9_E5:
case GL_R11F_G11F_B10F:
*outFormat = GL_RGB;
break;
case GL_RGB10_A2:
case GL_RGB5_A1:
*outFormat = GL_RGBA;
break;
// Depth
case GL_DEPTH_COMPONENT16:
case GL_DEPTH_COMPONENT24:
case GL_DEPTH_COMPONENT32:
case GL_DEPTH_COMPONENT32F:
case GL_DEPTH_COMPONENT:
*outFormat = GL_DEPTH_COMPONENT;
break;
// Depth Stencil
case GL_DEPTH32F_STENCIL8:
case GL_DEPTH_STENCIL:
*outFormat = GL_DEPTH_STENCIL;
break;
default:
MGLOG_E("NormalizePixelFormat: outFormat: unhandled internalFormat: %s", MG_Util::ConvertGLEnumToString(internalFormat).c_str());
// Fallback handling for other formats
// Try to infer format from internal format name
if (strstr(MG_Util::ConvertGLEnumToString(internalFormat).c_str(), "RGBA") != nullptr) {
*outFormat = GL_RGBA;
} else if (strstr(MG_Util::ConvertGLEnumToString(internalFormat).c_str(), "RGB") != nullptr) {
*outFormat = GL_RGB;
} else if (strstr(MG_Util::ConvertGLEnumToString(internalFormat).c_str(), "RG") != nullptr) {
*outFormat = GL_RG;
} else if (strstr(MG_Util::ConvertGLEnumToString(internalFormat).c_str(), "RED") != nullptr) {
*outFormat = GL_RED;
} else {
*outFormat = GL_RGBA; // Ultimate fallback
}
break;
} else {
*outFormat = GL_RGBA; // Ultimate fallback
}
break;
}
}
// type
if (outType) {
switch (internalFormat) {
// Color Unsigned Normalized
case GL_RGBA16:
case GL_RGB16:
case GL_RG16:
case GL_R16:
if (options & PixelFormatNormalizeOptionBit::NoNorm16) {
// converted to GL_RGBA32F
*outType = GL_FLOAT;
break;
} else {
*outType = GL_UNSIGNED_SHORT;
break;
}
case GL_RGBA8:
case GL_RGB8:
case GL_RG8:
case GL_R8:
*outType = GL_UNSIGNED_BYTE;
break;
// Color Signed Normalized
case GL_RGBA16_SNORM:
case GL_RGB16_SNORM:
case GL_RG16_SNORM:
case GL_R16_SNORM:
*outType = GL_SHORT;
break;
case GL_RGBA8_SNORM:
case GL_RGB8_SNORM:
case GL_RG8_SNORM:
case GL_R8_SNORM:
*outType = GL_BYTE;
break;
// Color Unsigned Integer
case GL_RGBA32UI:
case GL_RGB32UI:
case GL_RG32UI:
case GL_R32UI:
*outType = GL_UNSIGNED_INT;
break;
case GL_RGBA16UI:
case GL_RGB16UI:
case GL_RG16UI:
case GL_R16UI:
*outType = GL_UNSIGNED_SHORT;
break;
case GL_RGBA8UI:
case GL_RGB8UI:
case GL_RG8UI:
case GL_R8UI:
*outType = GL_UNSIGNED_BYTE;
break;
// Color Integer
case GL_RGBA32I:
case GL_RGB32I:
case GL_RG32I:
case GL_R32I:
*outType = GL_INT;
break;
case GL_RGBA16I:
case GL_RGB16I:
case GL_RG16I:
case GL_R16I:
*outType = GL_SHORT;
break;
case GL_RGBA8I:
case GL_RGB8I:
case GL_RG8I:
case GL_R8I:
*outType = GL_BYTE;
break;
// Color Float
case GL_RGBA32F:
case GL_RGB32F:
case GL_RG32F:
case GL_R32F:
// Color Unsigned Normalized
case GL_RGBA16:
case GL_RGB16:
case GL_RG16:
case GL_R16:
if (options & PixelFormatNormalizeOptionBit::NoNorm16) {
// converted to GL_RGBA32F
*outType = GL_FLOAT;
break;
case GL_RGBA16F:
case GL_RGB16F:
case GL_RG16F:
case GL_R16F:
*outType = GL_HALF_FLOAT;
break;
// Color sRGB
case GL_SRGB8:
*outType = GL_UNSIGNED_BYTE;
break;
// Color sized other
case GL_RGB9_E5:
*outType = GL_UNSIGNED_INT_5_9_9_9_REV;
break;
case GL_R11F_G11F_B10F:
*outType = GL_UNSIGNED_INT_10F_11F_11F_REV;
break;
case GL_RGB10_A2:
*outType = GL_UNSIGNED_INT_2_10_10_10_REV;
break;
case GL_RGB5_A1:
*outType = GL_UNSIGNED_SHORT_5_5_5_1;
break;
// Depth
case GL_DEPTH_COMPONENT16:
} else {
*outType = GL_UNSIGNED_SHORT;
break;
case GL_DEPTH_COMPONENT24:
*outType = GL_UNSIGNED_INT;
break;
case GL_DEPTH_COMPONENT32:
*outType = GL_UNSIGNED_INT;
break;
case GL_DEPTH_COMPONENT32F:
*outType = GL_FLOAT;
break;
case GL_DEPTH_COMPONENT:
*outType = GL_UNSIGNED_INT;
break;
}
case GL_RGBA8:
case GL_RGB8:
case GL_RG8:
case GL_R8:
*outType = GL_UNSIGNED_BYTE;
break;
// Depth Stencil
case GL_DEPTH32F_STENCIL8:
case GL_DEPTH_STENCIL:
*outType = GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
break;
// Color Signed Normalized
case GL_RGBA16_SNORM:
case GL_RGB16_SNORM:
case GL_RG16_SNORM:
case GL_R16_SNORM:
*outType = GL_SHORT;
break;
case GL_RGBA8_SNORM:
case GL_RGB8_SNORM:
case GL_RG8_SNORM:
case GL_R8_SNORM:
*outType = GL_BYTE;
break;
default:
MGLOG_E("NormalizePixelFormat: outType: unhandled internalFormat: %s", MG_Util::ConvertGLEnumToString(internalFormat).c_str());
// Fallback handling for other formats
*outType = GL_UNSIGNED_BYTE;
break;
// Color Unsigned Integer
case GL_RGBA32UI:
case GL_RGB32UI:
case GL_RG32UI:
case GL_R32UI:
*outType = GL_UNSIGNED_INT;
break;
case GL_RGBA16UI:
case GL_RGB16UI:
case GL_RG16UI:
case GL_R16UI:
*outType = GL_UNSIGNED_SHORT;
break;
case GL_RGBA8UI:
case GL_RGB8UI:
case GL_RG8UI:
case GL_R8UI:
*outType = GL_UNSIGNED_BYTE;
break;
// Color Integer
case GL_RGBA32I:
case GL_RGB32I:
case GL_RG32I:
case GL_R32I:
*outType = GL_INT;
break;
case GL_RGBA16I:
case GL_RGB16I:
case GL_RG16I:
case GL_R16I:
*outType = GL_SHORT;
break;
case GL_RGBA8I:
case GL_RGB8I:
case GL_RG8I:
case GL_R8I:
*outType = GL_BYTE;
break;
// Color Float
case GL_RGBA32F:
case GL_RGB32F:
case GL_RG32F:
case GL_R32F:
*outType = GL_FLOAT;
break;
case GL_RGBA16F:
case GL_RGB16F:
case GL_RG16F:
case GL_R16F:
*outType = GL_HALF_FLOAT;
break;
// Color sRGB
case GL_SRGB8:
*outType = GL_UNSIGNED_BYTE;
break;
// Color sized other
case GL_RGB9_E5:
*outType = GL_UNSIGNED_INT_5_9_9_9_REV;
break;
case GL_R11F_G11F_B10F:
*outType = GL_UNSIGNED_INT_10F_11F_11F_REV;
break;
case GL_RGB10_A2:
*outType = GL_UNSIGNED_INT_2_10_10_10_REV;
break;
case GL_RGB5_A1:
*outType = GL_UNSIGNED_SHORT_5_5_5_1;
break;
// Depth
case GL_DEPTH_COMPONENT16:
*outType = GL_UNSIGNED_SHORT;
break;
case GL_DEPTH_COMPONENT24:
*outType = GL_UNSIGNED_INT;
break;
case GL_DEPTH_COMPONENT32:
*outType = GL_UNSIGNED_INT;
break;
case GL_DEPTH_COMPONENT32F:
*outType = GL_FLOAT;
break;
case GL_DEPTH_COMPONENT:
*outType = GL_UNSIGNED_INT;
break;
// Depth Stencil
case GL_DEPTH32F_STENCIL8:
case GL_DEPTH_STENCIL:
*outType = GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
break;
default:
MGLOG_E("NormalizePixelFormat: outType: unhandled internalFormat: %s",
MG_Util::ConvertGLEnumToString(internalFormat).c_str());
// Fallback handling for other formats
*outType = GL_UNSIGNED_BYTE;
break;
}
}
}
@@ -9,10 +9,14 @@
#pragma once
#include <Includes.h>
namespace MobileGL::MG_Util::TextureFormatProcessor {
namespace MobileGL {
enum class PixelFormatNormalizeOptionBit : Uint {
NoNorm16 = 1 << 0,
None = 0,
};
void NormalizePixelFormat(GLenum internalFormat, Flags<PixelFormatNormalizeOptionBit> options, GLenum* outInternalFormat, GLenum* outFormat, GLenum* outType);
} // namespace MobileGL::MG_Util::TextureFormatProcessor
namespace MG_Util::TextureFormatProcessor {
void NormalizePixelFormat(GLenum internalFormat, Flags<PixelFormatNormalizeOptionBit> options,
GLenum* outInternalFormat, GLenum* outFormat, GLenum* outType);
}
} // namespace MobileGL
+7 -4
View File
@@ -145,17 +145,20 @@ namespace MobileGL {
using TargetEnum = typename ObjectType::TargetEnum;
BindingSlot() : m_target((TargetEnum)0), m_boundObject(nullptr) {}
explicit BindingSlot(TargetEnum target) : m_target(target), m_boundObject(nullptr) {}
void Bind(SharedPtr<ObjectType> object) {
if (m_boundObject == object) return;
void Bind(SharedPtr<ObjectType> object) { m_boundObject = object; }
m_boundObject = object;
++m_version;
}
SharedPtr<ObjectType> GetBoundObject() const { return m_boundObject; }
TargetEnum GetTarget() const { return m_target; }
Uint16 GetVersion() const { return m_version; }
private:
TargetEnum m_target;
Uint16 m_version = 0;
SharedPtr<ObjectType> m_boundObject;
};
+1 -1
View File
@@ -91,7 +91,7 @@ If you want to try the project right now, youll need to build it yourself:
## Build Options
| Option | Description | Default |
| ---------------------------- | ----------------------------------------------------- | ------- |
|------------------------------| ----------------------------------------------------- | ------- |
| `MOBILEGL_BUILD_TEST` | Build MobileGL tests (requires Clang) | ON |
| `MOBILEGL_BUILD_BENCHMARK` | Build MobileGL benchmarks (requires Clang) | ON |
| `MOBILEGL_FORCE_RELEASE_OPT` | Enable O3 and LTO in Debug build | ON |
+1 -1
View File
@@ -11,7 +11,7 @@ android {
// externalNativeBuild {
// cmake {
// arguments "-DTRACY_ENABLE=ON"
// arguments "-DMOBILEGL_ENABLE_TRACY=ON"
// }
// }
}