mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 14:18:31 +09:00
[Feat|Perf] (*/BufferState): Improve dirty mark for Buffer.
This commit is contained in:
@@ -103,7 +103,9 @@ set(SOURCE_FILES
|
|||||||
|
|
||||||
MobileGL/MG_Util/Debug/Log.cpp
|
MobileGL/MG_Util/Debug/Log.cpp
|
||||||
|
|
||||||
|
MobileGL/MG_Util/Math/VectorTypes.cpp
|
||||||
MobileGL/MG_Util/Metrics/TextureMetrics.cpp
|
MobileGL/MG_Util/Metrics/TextureMetrics.cpp
|
||||||
|
|
||||||
MobileGL/MG_Util/Metrics/BufferMetrics.cpp
|
MobileGL/MG_Util/Metrics/BufferMetrics.cpp
|
||||||
|
|
||||||
MobileGL/MG_Util/Converters/GLToStr/GLEnumConverter.cpp
|
MobileGL/MG_Util/Converters/GLToStr/GLEnumConverter.cpp
|
||||||
|
|||||||
@@ -151,6 +151,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
|
|
||||||
// Do real sync
|
// Do real sync
|
||||||
for (auto& bufferObject : buffersToSync) {
|
for (auto& bufferObject : buffersToSync) {
|
||||||
|
if (!(bufferObject->GetChangeBits() & BufferChangeBits::DirtyBit)) continue;
|
||||||
|
|
||||||
const auto& backendBufferIt = g_backendBufferObjects.find(bufferObject);
|
const auto& backendBufferIt = g_backendBufferObjects.find(bufferObject);
|
||||||
SharedPtr<BackendBufferObject> backendBufferObject;
|
SharedPtr<BackendBufferObject> backendBufferObject;
|
||||||
if (backendBufferIt == g_backendBufferObjects.end()) {
|
if (backendBufferIt == g_backendBufferObjects.end()) {
|
||||||
@@ -778,8 +780,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) {
|
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 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,
|
MGLOG_D("ES %s(%d, %d, %d, %d, %d, %d, %d, %d, 0x%x, %s)", __func__, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
|
||||||
MG_Util::ConvertGLEnumToString(filter).c_str());
|
dstX1, dstY1, mask, MG_Util::ConvertGLEnumToString(filter).c_str());
|
||||||
MG_External::GLES::glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
|
MG_External::GLES::glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
|
||||||
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) {
|
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 error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
|
||||||
@@ -842,12 +844,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
|
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!UpdateTextureBindingAtTarget(target))
|
if (!UpdateTextureBindingAtTarget(target)) return;
|
||||||
return;
|
|
||||||
|
|
||||||
// GLint realInternalFormat;
|
// GLint realInternalFormat;
|
||||||
// MG_External::GLES::glGetTexLevelParameteriv(target, level, GL_TEXTURE_INTERNAL_FORMAT, &realInternalFormat);
|
// MG_External::GLES::glGetTexLevelParameteriv(target, level, GL_TEXTURE_INTERNAL_FORMAT,
|
||||||
// errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) {
|
// &realInternalFormat); 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 error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
|
||||||
// });
|
// });
|
||||||
// internalformat = (GLenum)realInternalFormat;
|
// internalformat = (GLenum)realInternalFormat;
|
||||||
@@ -856,11 +857,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
GLenum format = GL_DEPTH_COMPONENT;
|
GLenum format = GL_DEPTH_COMPONENT;
|
||||||
GLenum type = GL_UNSIGNED_INT;
|
GLenum type = GL_UNSIGNED_INT;
|
||||||
TextureImpl::GenerateTextureFormatInfo(mglInternalFormat, &internalformat, &format, &type);
|
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",
|
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(),
|
MG_Util::ConvertTextureInternalFormatToString(mglInternalFormat).c_str(),
|
||||||
MG_Util::ConvertGLEnumToString(internalformat).c_str(),
|
MG_Util::ConvertGLEnumToString(internalformat).c_str(),
|
||||||
MG_Util::ConvertGLEnumToString(format).c_str(),
|
MG_Util::ConvertGLEnumToString(format).c_str(), MG_Util::ConvertGLEnumToString(type).c_str());
|
||||||
MG_Util::ConvertGLEnumToString(type).c_str());
|
|
||||||
TexturePixelDataType texturePixelDataType = MG_Util::ConvertGLEnumToTexturePixelDataType(type);
|
TexturePixelDataType texturePixelDataType = MG_Util::ConvertGLEnumToTexturePixelDataType(type);
|
||||||
|
|
||||||
bool isDepthFormat =
|
bool isDepthFormat =
|
||||||
@@ -938,8 +939,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
|
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!UpdateTextureBindingAtTarget(target))
|
if (!UpdateTextureBindingAtTarget(target)) return;
|
||||||
return;
|
|
||||||
|
|
||||||
BindCurrentFBO(FramebufferTarget::Read);
|
BindCurrentFBO(FramebufferTarget::Read);
|
||||||
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) {
|
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) {
|
||||||
|
|||||||
@@ -7,24 +7,24 @@
|
|||||||
// End of Source File Header
|
// End of Source File Header
|
||||||
|
|
||||||
#include "Managers.h"
|
#include "Managers.h"
|
||||||
#include "MG_Backend/Backends.h"
|
|
||||||
#include "MG_Util/Debug/Log.h"
|
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
#include "DirectGLES.h"
|
#include "DirectGLES.h"
|
||||||
#include "MG_State/GLState/TextureState/TextureObjectBuffer.h"
|
|
||||||
|
|
||||||
#include <MG_Util/BackendLoaders/OpenGL/Loader.h>
|
#include <MG_Util/BackendLoaders/OpenGL/Loader.h>
|
||||||
#include <MG_Util/Converters/GLToStr/GLEnumConverter.h>
|
#include <MG_Util/Converters/GLToStr/GLEnumConverter.h>
|
||||||
#include <MG_Util/Converters/MGToStr/TextureEnumConverter.h>
|
|
||||||
#include <MG_Util/Converters/MGToGL/DataTypeConverter.h>
|
#include <MG_Util/Converters/MGToGL/DataTypeConverter.h>
|
||||||
#include <MG_Util/Converters/MGToGL/BufferEnumConverter.h>
|
#include <MG_Util/Converters/MGToGL/BufferEnumConverter.h>
|
||||||
#include <MG_Util/Converters/MGToGL/TextureEnumConverter.h>
|
|
||||||
#include <MG_Util/Converters/MGToGL/ProgramEnumConverter.h>
|
#include <MG_Util/Converters/MGToGL/ProgramEnumConverter.h>
|
||||||
|
#include <MG_Util/Converters/MGToGL/TextureEnumConverter.h>
|
||||||
|
#include <MG_Util/Converters/MGToStr/TextureEnumConverter.h>
|
||||||
|
#include <MG_State/GLState/TextureState/TextureObjectBuffer.h>
|
||||||
#include <MG_Util/Converters/GLToMG/FramebufferEnumConverter.h>
|
#include <MG_Util/Converters/GLToMG/FramebufferEnumConverter.h>
|
||||||
#include <MG_Util/Converters/MGToGL/FramebufferEnumConverter.h>
|
#include <MG_Util/Converters/MGToGL/FramebufferEnumConverter.h>
|
||||||
#include <MG_State/GLState/FramebufferState/FramebufferObject.h>
|
#include <MG_State/GLState/FramebufferState/FramebufferObject.h>
|
||||||
|
|
||||||
namespace MobileGL::MG_Backend::DirectGLES {
|
namespace MobileGL::MG_Backend::DirectGLES {
|
||||||
|
constexpr Bool PREFER_MAP_BUFFER_RANGE_FOR_BUFFER_SYNC = true;
|
||||||
|
|
||||||
namespace BufferImpl {
|
namespace BufferImpl {
|
||||||
BackendBufferObject::BackendBufferObject() {
|
BackendBufferObject::BackendBufferObject() {
|
||||||
#ifdef TRACY_ENABLE
|
#ifdef TRACY_ENABLE
|
||||||
@@ -58,8 +58,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
MGLOG_D("Syncing buffer object with backend ID %u to backend for state ID %u", m_backendBufferId,
|
MGLOG_D("Syncing buffer object with backend ID %u to backend for state ID %u", m_backendBufferId,
|
||||||
stateBufferObject->GetExternalIndex());
|
stateBufferObject->GetExternalIndex());
|
||||||
|
|
||||||
|
// Decide sync method
|
||||||
|
// glBufferData
|
||||||
Bool needsRegeneration =
|
Bool needsRegeneration =
|
||||||
!m_isInitialized || bufferSize > m_prevBufferSize || bufferSize < m_prevBufferSize / 2;
|
!m_isInitialized || (stateBufferObject->GetChangeBits() & BufferChangeBits::PreferReallocationBit);
|
||||||
|
|
||||||
if (needsRegeneration) {
|
if (needsRegeneration) {
|
||||||
MGLOG_D("Buffer size changed significantly or not initialized, regenerating buffer with ID: %u",
|
MGLOG_D("Buffer size changed significantly or not initialized, regenerating buffer with ID: %u",
|
||||||
@@ -67,22 +69,33 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
SyncToBackend_glBufferData(stateBufferObject);
|
SyncToBackend_glBufferData(stateBufferObject);
|
||||||
m_isInitialized = true;
|
m_isInitialized = true;
|
||||||
m_prevBufferSize = bufferSize;
|
m_prevBufferSize = bufferSize;
|
||||||
|
stateBufferObject->ClearDirty();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (stateBufferObject->GetUsage()) {
|
// glMapBufferRange or glBufferSubData
|
||||||
case BufferUsage::StaticDraw:
|
Bool useInvalidationMap = !(stateBufferObject->GetChangeBits() & BufferChangeBits::ForbidInvalidationBit);
|
||||||
SyncToBackend_glBufferSubData(stateBufferObject);
|
Bool useUnsynchronizedMap =
|
||||||
break;
|
!(stateBufferObject->GetChangeBits() & BufferChangeBits::ForbidUnsynchronizationBit);
|
||||||
case BufferUsage::DynamicDraw:
|
Bool useMapBufferRange = useInvalidationMap || useUnsynchronizedMap;
|
||||||
case BufferUsage::StreamDraw:
|
|
||||||
SyncToBackend_glMapBufferRange(stateBufferObject);
|
if (!useMapBufferRange && PREFER_MAP_BUFFER_RANGE_FOR_BUFFER_SYNC) {
|
||||||
break;
|
auto usage = stateBufferObject->GetUsage();
|
||||||
default:
|
if (usage == BufferUsage::DynamicDraw || usage == BufferUsage::StreamDraw ||
|
||||||
SyncToBackend_glBufferSubData(stateBufferObject);
|
usage == BufferUsage::StreamCopy || usage == BufferUsage::DynamicCopy) {
|
||||||
break;
|
useMapBufferRange = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (useMapBufferRange) {
|
||||||
|
MGLOG_D("Using glMapBufferRange to sync buffer with ID: %u", m_backendBufferId);
|
||||||
|
SyncToBackend_glMapBufferRange(stateBufferObject, useInvalidationMap, useUnsynchronizedMap);
|
||||||
|
} else {
|
||||||
|
MGLOG_D("Using glBufferSubData to sync buffer with ID: %u", m_backendBufferId);
|
||||||
|
SyncToBackend_glBufferSubData(stateBufferObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear dirty state
|
||||||
stateBufferObject->ClearDirty();
|
stateBufferObject->ClearDirty();
|
||||||
m_prevBufferSize = bufferSize;
|
m_prevBufferSize = bufferSize;
|
||||||
}
|
}
|
||||||
@@ -102,8 +115,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
|
|
||||||
MG_External::GLES::glBindBuffer(TempBufferTarget, m_backendBufferId);
|
MG_External::GLES::glBindBuffer(TempBufferTarget, m_backendBufferId);
|
||||||
MG_External::GLES::glBufferData(TempBufferTarget, size, data, usage);
|
MG_External::GLES::glBufferData(TempBufferTarget, size, data, usage);
|
||||||
|
|
||||||
stateBufferObject->ClearDirty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BackendBufferObject::SyncToBackend_glBufferSubData(
|
void BackendBufferObject::SyncToBackend_glBufferSubData(
|
||||||
@@ -117,19 +128,21 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
|
|
||||||
const void* data = stateBufferObject->GetDataReadOnly()->data();
|
const void* data = stateBufferObject->GetDataReadOnly()->data();
|
||||||
// dirty range: [range.start, range.end)
|
// dirty range: [range.start, range.end)
|
||||||
const auto& range = stateBufferObject->GetDirtyRange();
|
auto ranges = stateBufferObject->GetDirtyRanges();
|
||||||
if (range.end == 0) {
|
if (ranges.empty()) {
|
||||||
MGLOG_D("No dirty range to sync for buffer with ID: %u", m_backendBufferId);
|
MGLOG_D("No dirty range to sync for buffer with ID: %u", m_backendBufferId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const auto& range : ranges) {
|
||||||
MG_External::GLES::glBindBuffer(TempBufferTarget, m_backendBufferId);
|
MG_External::GLES::glBindBuffer(TempBufferTarget, m_backendBufferId);
|
||||||
MG_External::GLES::glBufferSubData(TempBufferTarget, range.start, range.end - range.start,
|
MG_External::GLES::glBufferSubData(TempBufferTarget, range.start, range.end - range.start,
|
||||||
reinterpret_cast<const char*>(data) + range.start);
|
reinterpret_cast<const char*>(data) + range.start);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BackendBufferObject::SyncToBackend_glMapBufferRange(
|
void BackendBufferObject::SyncToBackend_glMapBufferRange(
|
||||||
SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject, Bool invalidate) {
|
SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject, Bool invalidate, Bool unsynchronized) {
|
||||||
#ifdef TRACY_ENABLE
|
#ifdef TRACY_ENABLE
|
||||||
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
|
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
|
||||||
#endif
|
#endif
|
||||||
@@ -137,19 +150,27 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
|
|
||||||
MGLOG_D("Syncing buffer map (glMapBuffer) for object with ID : %u", m_backendBufferId);
|
MGLOG_D("Syncing buffer map (glMapBuffer) for object with ID : %u", m_backendBufferId);
|
||||||
MGLOG_D("Mapping buffer with ID: %u", m_backendBufferId);
|
MGLOG_D("Mapping buffer with ID: %u", m_backendBufferId);
|
||||||
const auto& range = stateBufferObject->GetDirtyRange();
|
auto ranges = stateBufferObject->GetDirtyRanges();
|
||||||
if (range.end == 0) {
|
if (ranges.empty()) {
|
||||||
MGLOG_D("No dirty range to sync for buffer with ID: %u", m_backendBufferId);
|
MGLOG_D("No dirty range to sync for buffer with ID: %u", m_backendBufferId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
SizeT minStart = ranges.GetOverallMinStart();
|
||||||
|
SizeT maxEnd = ranges.GetOverallMaxEnd();
|
||||||
MG_External::GLES::glBindBuffer(TempBufferTarget, m_backendBufferId);
|
MG_External::GLES::glBindBuffer(TempBufferTarget, m_backendBufferId);
|
||||||
void* mappedData =
|
void* mappedData = MG_External::GLES::glMapBufferRange(
|
||||||
MG_External::GLES::glMapBufferRange(TempBufferTarget, range.start, range.end - range.start,
|
TempBufferTarget, minStart, maxEnd - minStart,
|
||||||
(invalidate ? GL_MAP_INVALIDATE_BUFFER_BIT : 0) | GL_MAP_WRITE_BIT);
|
(invalidate ? GL_MAP_INVALIDATE_RANGE_BIT : 0) | (unsynchronized ? GL_MAP_UNSYNCHRONIZED_BIT : 0) |
|
||||||
|
GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
|
||||||
const void* data = stateBufferObject->GetDataReadOnly()->data();
|
const void* data = stateBufferObject->GetDataReadOnly()->data();
|
||||||
if (mappedData) {
|
if (mappedData) {
|
||||||
Memcpy(mappedData, ((const char*)(data) + range.start), range.end - range.start);
|
|
||||||
MGLOG_D("Mapped buffer data successfully for object with ID: %u", m_backendBufferId);
|
MGLOG_D("Mapped buffer data successfully for object with ID: %u", m_backendBufferId);
|
||||||
|
Memcpy(mappedData, reinterpret_cast<const char*>(data) + minStart, maxEnd - minStart);
|
||||||
|
// Explicitly flush the dirty ranges
|
||||||
|
for (const auto& range : ranges) {
|
||||||
|
MG_External::GLES::glFlushMappedBufferRange(TempBufferTarget, range.start - minStart,
|
||||||
|
range.end - range.start);
|
||||||
|
}
|
||||||
MG_External::GLES::glUnmapBuffer(TempBufferTarget);
|
MG_External::GLES::glUnmapBuffer(TempBufferTarget);
|
||||||
} else {
|
} else {
|
||||||
MGLOG_E("Failed to map buffer with ID: %u", m_backendBufferId);
|
MGLOG_E("Failed to map buffer with ID: %u", m_backendBufferId);
|
||||||
@@ -328,7 +349,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
// 4. Mipmap levels changed
|
// 4. Mipmap levels changed
|
||||||
|
|
||||||
if (!stateTextureObject->IsComplete()) {
|
if (!stateTextureObject->IsComplete()) {
|
||||||
MGLOG_D("Texture object with ID: %u is not complete, skipping sync.", stateTextureObject->GetExternalIndex());
|
MGLOG_D("Texture object with ID: %u is not complete, skipping sync.",
|
||||||
|
stateTextureObject->GetExternalIndex());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -376,9 +398,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
auto* pData = (levelDirty && levelByteSize != 0)
|
auto* pData = (levelDirty && levelByteSize != 0)
|
||||||
? textureMipmapObject->MapMipmapData(uploadTarget, level)
|
? textureMipmapObject->MapMipmapData(uploadTarget, level)
|
||||||
: nullptr;
|
: nullptr;
|
||||||
MGLOG_D("%s: target: %s: syncing mip %d: %dx%dx%d, byteSize = %d, pData = %p, levelDirty = %s", __func__,
|
MGLOG_D(
|
||||||
MG_Util::ConvertTextureUploadTargetToString(uploadTarget).c_str(), level,
|
"%s: target: %s: syncing mip %d: %dx%dx%d, byteSize = %d, pData = %p, levelDirty = %s",
|
||||||
levelTexelSize.x(), levelTexelSize.y(), levelTexelSize.z(), levelByteSize, pData, levelDirty ? "true" : "false");
|
__func__, MG_Util::ConvertTextureUploadTargetToString(uploadTarget).c_str(), level,
|
||||||
|
levelTexelSize.x(), levelTexelSize.y(), levelTexelSize.z(), levelByteSize, pData,
|
||||||
|
levelDirty ? "true" : "false");
|
||||||
|
|
||||||
errorLopper.Clear();
|
errorLopper.Clear();
|
||||||
MG_External::GLES::glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
MG_External::GLES::glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
@@ -386,29 +410,30 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
// TODO: handle more texture types
|
// TODO: handle more texture types
|
||||||
switch (textureTarget) {
|
switch (textureTarget) {
|
||||||
case TextureTarget::Texture2D:
|
case TextureTarget::Texture2D:
|
||||||
case TextureTarget::TextureCubeMap:
|
case TextureTarget::TextureCubeMap: {
|
||||||
{
|
MG_External::GLES::glTexImage2D(
|
||||||
MG_External::GLES::glTexImage2D(glUploadTarget, static_cast<GLint>(level), glInternalFormat,
|
glUploadTarget, static_cast<GLint>(level), glInternalFormat,
|
||||||
static_cast<GLsizei>(levelTexelSize.x()),
|
static_cast<GLsizei>(levelTexelSize.x()), static_cast<GLsizei>(levelTexelSize.y()),
|
||||||
static_cast<GLsizei>(levelTexelSize.y()), 0, glFormat,
|
0, glFormat, glType, pData);
|
||||||
glType, pData);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TextureTarget::Texture3D: {
|
case TextureTarget::Texture3D: {
|
||||||
MG_External::GLES::glTexImage3D(glUploadTarget, static_cast<GLint>(level), glInternalFormat,
|
MG_External::GLES::glTexImage3D(
|
||||||
static_cast<GLsizei>(levelTexelSize.x()),
|
glUploadTarget, static_cast<GLint>(level), glInternalFormat,
|
||||||
static_cast<GLsizei>(levelTexelSize.y()),
|
static_cast<GLsizei>(levelTexelSize.x()), static_cast<GLsizei>(levelTexelSize.y()),
|
||||||
static_cast<GLsizei>(levelTexelSize.z()),
|
static_cast<GLsizei>(levelTexelSize.z()), 0, glFormat, glType, pData);
|
||||||
0, glFormat,
|
|
||||||
glType, pData);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
MGLOG_E("Unhandled texture target %s", MG_Util::ConvertTextureTargetToString(textureTarget).c_str());
|
MGLOG_E("Unhandled texture target %s",
|
||||||
|
MG_Util::ConvertTextureTargetToString(textureTarget).c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__, glUploadTarget, glInternalFormat, glFormat, glType, pData](GLenum err) {
|
errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__, glUploadTarget,
|
||||||
MGLOG_D("%s(%s:%d) ES error: %s. glTexImage*: target=%s, internalformat=%s, format=%s, type=%s, pixels=%p", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str(),
|
glInternalFormat, glFormat, glType, pData](GLenum err) {
|
||||||
|
MGLOG_D("%s(%s:%d) ES error: %s. glTexImage*: target=%s, internalformat=%s, format=%s, "
|
||||||
|
"type=%s, pixels=%p",
|
||||||
|
func, file, line, MG_Util::ConvertGLEnumToString(err).c_str(),
|
||||||
MG_Util::ConvertGLEnumToString(glUploadTarget).c_str(),
|
MG_Util::ConvertGLEnumToString(glUploadTarget).c_str(),
|
||||||
MG_Util::ConvertGLEnumToString(glInternalFormat).c_str(),
|
MG_Util::ConvertGLEnumToString(glInternalFormat).c_str(),
|
||||||
MG_Util::ConvertGLEnumToString(glFormat).c_str(),
|
MG_Util::ConvertGLEnumToString(glFormat).c_str(),
|
||||||
@@ -493,8 +518,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
auto backendId = backendBufferObject->GetBackendBufferId();
|
auto backendId = backendBufferObject->GetBackendBufferId();
|
||||||
|
|
||||||
GLenum glInternalFormat, glType, glFormat;
|
GLenum glInternalFormat, glType, glFormat;
|
||||||
TextureImpl::GenerateTextureFormatInfo(textureBufferObject->GetFormat(), &glInternalFormat,
|
TextureImpl::GenerateTextureFormatInfo(textureBufferObject->GetFormat(), &glInternalFormat, &glFormat,
|
||||||
&glFormat, &glType);
|
&glType);
|
||||||
|
|
||||||
MG_External::GLES::glTexBuffer(GL_TEXTURE_BUFFER, glInternalFormat, backendId);
|
MG_External::GLES::glTexBuffer(GL_TEXTURE_BUFFER, glInternalFormat, backendId);
|
||||||
break;
|
break;
|
||||||
@@ -1129,8 +1154,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
Int width = static_cast<Int>(stateRBOObject->GetWidth());
|
Int width = static_cast<Int>(stateRBOObject->GetWidth());
|
||||||
Int height = static_cast<Int>(stateRBOObject->GetHeight());
|
Int height = static_cast<Int>(stateRBOObject->GetHeight());
|
||||||
GLenum glInternalFormat, glType, glFormat;
|
GLenum glInternalFormat, glType, glFormat;
|
||||||
TextureImpl::GenerateTextureFormatInfo(internalFormat, &glInternalFormat,
|
TextureImpl::GenerateTextureFormatInfo(internalFormat, &glInternalFormat, &glFormat, &glType);
|
||||||
&glFormat, &glType);
|
|
||||||
|
|
||||||
MG_External::GLES::glRenderbufferStorage(GL_RENDERBUFFER, glInternalFormat, static_cast<GLsizei>(width),
|
MG_External::GLES::glRenderbufferStorage(GL_RENDERBUFFER, glInternalFormat, static_cast<GLsizei>(width),
|
||||||
static_cast<GLsizei>(height));
|
static_cast<GLsizei>(height));
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
void SyncToBackend_glBufferData(SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject);
|
void SyncToBackend_glBufferData(SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject);
|
||||||
void SyncToBackend_glBufferSubData(SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject);
|
void SyncToBackend_glBufferSubData(SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject);
|
||||||
void SyncToBackend_glMapBufferRange(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;
|
Uint m_backendBufferId = 0;
|
||||||
SizeT m_prevBufferSize = 0;
|
SizeT m_prevBufferSize = 0;
|
||||||
@@ -58,12 +58,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
|
|
||||||
namespace TextureImpl {
|
namespace TextureImpl {
|
||||||
inline Bool IsSupportedTextureTarget(TextureTarget target) {
|
inline Bool IsSupportedTextureTarget(TextureTarget target) {
|
||||||
if (target == TextureTarget::Texture1D ||
|
if (target == TextureTarget::Texture1D || target == TextureTarget::TextureRectangle ||
|
||||||
target == TextureTarget::TextureRectangle ||
|
target == TextureTarget::Texture2DMultisampleArray || target == TextureTarget::Texture1DArray ||
|
||||||
target == TextureTarget::Texture2DMultisampleArray ||
|
target == TextureTarget::Texture2DMultisample || target == TextureTarget::Texture2DArray)
|
||||||
target == TextureTarget::Texture1DArray ||
|
|
||||||
target == TextureTarget::Texture2DMultisample ||
|
|
||||||
target == TextureTarget::Texture2DArray)
|
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,13 +74,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
|
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
|
||||||
#endif
|
#endif
|
||||||
using namespace MobileGL::MG_Util::TextureFormatProcessor;
|
using namespace MobileGL::MG_Util::TextureFormatProcessor;
|
||||||
auto options =
|
auto options = (MG_External::GLES::g_glesCaps.hasNorm16Texture) ? PixelFormatNormalizeOptionBit::None
|
||||||
(MG_External::GLES::g_glesCaps.hasNorm16Texture) ? PixelFormatNormalizeOptionBit::None : PixelFormatNormalizeOptionBit::NoNorm16;
|
: PixelFormatNormalizeOptionBit::NoNorm16;
|
||||||
NormalizePixelFormat(
|
NormalizePixelFormat(MG_Util::ConvertTextureInternalFormatToGLEnum(internalFormat), options,
|
||||||
MG_Util::ConvertTextureInternalFormatToGLEnum(internalFormat),
|
outInternalFormat, outFormat, outType);
|
||||||
options,
|
|
||||||
outInternalFormat,
|
|
||||||
outFormat, outType);
|
|
||||||
}
|
}
|
||||||
} // namespace TextureImpl
|
} // namespace TextureImpl
|
||||||
|
|
||||||
|
|||||||
@@ -174,47 +174,41 @@ namespace MobileGL {
|
|||||||
return MG_External::EGL::eglCreateSync(dpy, type, attrib_list);
|
return MG_External::EGL::eglCreateSync(dpy, type, attrib_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EGLBoolean DestroySync(EGLDisplay dpy, EGLSync sync) {
|
EGLBoolean DestroySync(EGLDisplay dpy, EGLSync sync) {
|
||||||
return MG_External::EGL::eglDestroySync(dpy, sync);
|
return MG_External::EGL::eglDestroySync(dpy, sync);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EGLint ClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout) {
|
EGLint ClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout) {
|
||||||
return MG_External::EGL::eglClientWaitSync(dpy, sync, flags, 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);
|
return MG_External::EGL::eglGetSyncAttrib(dpy, sync, attribute, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EGLImage CreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer,
|
||||||
EGLImage CreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib * attrib_list) {
|
const EGLAttrib* attrib_list) {
|
||||||
return MG_External::EGL::eglCreateImage(dpy, ctx, target, buffer, attrib_list);
|
return MG_External::EGL::eglCreateImage(dpy, ctx, target, buffer, attrib_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EGLBoolean DestroyImage(EGLDisplay dpy, EGLImage image) {
|
EGLBoolean DestroyImage(EGLDisplay dpy, EGLImage image) {
|
||||||
return MG_External::EGL::eglDestroyImage(dpy, 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);
|
return MG_External::EGL::eglGetPlatformDisplay(platform, native_display, attrib_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EGLSurface CreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void* native_window,
|
||||||
EGLSurface CreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void * native_window, const EGLAttrib * attrib_list) {
|
const EGLAttrib* attrib_list) {
|
||||||
return MG_External::EGL::eglCreatePlatformWindowSurface(dpy, config, native_window, attrib_list);
|
return MG_External::EGL::eglCreatePlatformWindowSurface(dpy, config, native_window, attrib_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EGLSurface CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void* native_pixmap,
|
||||||
EGLSurface CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void * native_pixmap, const EGLAttrib * attrib_list) {
|
const EGLAttrib* attrib_list) {
|
||||||
return MG_External::EGL::eglCreatePlatformPixmapSurface(dpy, config, native_pixmap, attrib_list);
|
return MG_External::EGL::eglCreatePlatformPixmapSurface(dpy, config, native_pixmap, attrib_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EGLBoolean WaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags) {
|
EGLBoolean WaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags) {
|
||||||
return MG_External::EGL::eglWaitSync(dpy, sync, flags);
|
return MG_External::EGL::eglWaitSync(dpy, sync, flags);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,11 +53,14 @@ namespace MobileGL {
|
|||||||
EGLBoolean DestroySync(EGLDisplay dpy, EGLSync sync);
|
EGLBoolean DestroySync(EGLDisplay dpy, EGLSync sync);
|
||||||
EGLint ClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout);
|
EGLint ClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout);
|
||||||
EGLBoolean GetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib* value);
|
EGLBoolean GetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib* 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);
|
||||||
EGLBoolean DestroyImage(EGLDisplay dpy, EGLImage image);
|
EGLBoolean DestroyImage(EGLDisplay dpy, EGLImage image);
|
||||||
EGLDisplay GetPlatformDisplay(EGLenum platform, void* native_display, 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 CreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void* native_window,
|
||||||
EGLSurface CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void * native_pixmap, const EGLAttrib * attrib_list);
|
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);
|
EGLBoolean WaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags);
|
||||||
} // namespace MG_Impl::EGLImpl
|
} // namespace MG_Impl::EGLImpl
|
||||||
} // namespace MobileGL
|
} // namespace MobileGL
|
||||||
|
|||||||
@@ -525,8 +525,7 @@ namespace MobileGL {
|
|||||||
auto& point = MG_State::pGLContext->GetBufferBindingPoint(bufferTarget, pointIndex);
|
auto& point = MG_State::pGLContext->GetBufferBindingPoint(bufferTarget, pointIndex);
|
||||||
point.Bind(bufferObject);
|
point.Bind(bufferObject);
|
||||||
point.SetRange(Range1D(0, bufferObject->GetSize()));
|
point.SetRange(Range1D(0, bufferObject->GetSize()));
|
||||||
MGLOG_D("%s: set range (0, %d)", __func__,
|
MGLOG_D("%s: set range (0, %d)", __func__, bufferObject->GetSize());
|
||||||
bufferObject->GetSize());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BindBufferRange_State(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) {
|
void BindBufferRange_State(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) {
|
||||||
@@ -575,6 +574,7 @@ namespace MobileGL {
|
|||||||
return MapBuffer_State(target, access);
|
return MapBuffer_State(target, access);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: this should be a "backend" function
|
||||||
void CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset,
|
void CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset,
|
||||||
GLsizeiptr size) {
|
GLsizeiptr size) {
|
||||||
CopyBufferSubData_State(readTarget, writeTarget, readOffset, writeOffset, size);
|
CopyBufferSubData_State(readTarget, writeTarget, readOffset, writeOffset, size);
|
||||||
|
|||||||
@@ -12,16 +12,22 @@
|
|||||||
namespace MobileGL {
|
namespace MobileGL {
|
||||||
namespace MG_Impl::GLImpl {
|
namespace MG_Impl::GLImpl {
|
||||||
/* @INSERTION_POINT:FUNCTION_DECLARATION@ */
|
/* @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 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 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 DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices,
|
||||||
void DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instancecount, GLint basevertex);
|
GLsizei instancecount, GLint basevertex, GLuint baseinstance);
|
||||||
void DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instancecount, 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 DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instancecount);
|
||||||
void DrawElementsIndirect(GLenum mode, GLenum type, const void* indirect);
|
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 DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
|
||||||
void DrawArraysIndirect(GLenum mode, const void* indirect);
|
void DrawArraysIndirect(GLenum mode, const void* indirect);
|
||||||
void DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const void* indices, GLint basevertex);
|
void DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const void* indices, GLint basevertex);
|
||||||
|
|||||||
@@ -516,15 +516,15 @@ namespace MobileGL {
|
|||||||
void Uniform_State(MG_State::GLState::ProgramObject& programObject, GLuint location, T* value,
|
void Uniform_State(MG_State::GLState::ProgramObject& programObject, GLuint location, T* value,
|
||||||
SizeT byteOffsetInsideUniform = 0) {
|
SizeT byteOffsetInsideUniform = 0) {
|
||||||
if (!programObject.IsUniformOpaqueAtLocation(location)) {
|
if (!programObject.IsUniformOpaqueAtLocation(location)) {
|
||||||
MGLOG_D("%s: program = %d, location = %d, maxLocation = %d", __func__,
|
MGLOG_D("%s: program = %d, location = %d, maxLocation = %d", __func__, programObject.GetExternalIndex(),
|
||||||
programObject.GetExternalIndex(), location, programObject.GetMaxUniformLocation());
|
location, programObject.GetMaxUniformLocation());
|
||||||
auto size = programObject.GetUniformSizesInBytes(location);
|
auto size = programObject.GetUniformSizesInBytes(location);
|
||||||
auto offset = programObject.GetUniformOffset(location);
|
auto offset = programObject.GetUniformOffset(location);
|
||||||
MOBILEGL_ASSERT(size >= ItemCount * sizeof(T),
|
MOBILEGL_ASSERT(size >= ItemCount * sizeof(T),
|
||||||
"Uniform size mismatch, expected at least %zu bytes, got %zu bytes.",
|
"Uniform size mismatch, expected at least %zu bytes, got %zu bytes.",
|
||||||
ItemCount * sizeof(T), size);
|
ItemCount * sizeof(T), size);
|
||||||
MGLOG_D("%s: program = %d, location = %d, byteOffset = %d", __func__,
|
MGLOG_D("%s: program = %d, location = %d, byteOffset = %d", __func__, programObject.GetExternalIndex(),
|
||||||
programObject.GetExternalIndex(), location, offset + byteOffsetInsideUniform);
|
location, offset + byteOffsetInsideUniform);
|
||||||
Memcpy((char*)programObject.MapUBO() + offset + byteOffsetInsideUniform, value, ItemCount * sizeof(T));
|
Memcpy((char*)programObject.MapUBO() + offset + byteOffsetInsideUniform, value, ItemCount * sizeof(T));
|
||||||
} else {
|
} else {
|
||||||
auto* ttype = programObject.GetUniformTType(location);
|
auto* ttype = programObject.GetUniformTType(location);
|
||||||
|
|||||||
@@ -63,8 +63,7 @@ namespace MobileGL {
|
|||||||
// TextureInternalFormat textureInternalFormat =
|
// TextureInternalFormat textureInternalFormat =
|
||||||
// MG_Util::ConvertGLEnumToTextureInternalFormat(format);
|
// MG_Util::ConvertGLEnumToTextureInternalFormat(format);
|
||||||
MGLOG_D("TexSubImage2D_State: target = %s, level = %d, (%d, %d), format = %s, pixels = %p",
|
MGLOG_D("TexSubImage2D_State: target = %s, level = %d, (%d, %d), format = %s, pixels = %p",
|
||||||
MG_Util::ConvertGLEnumToString(target).c_str(), level,
|
MG_Util::ConvertGLEnumToString(target).c_str(), level, width, height,
|
||||||
width, height,
|
|
||||||
MG_Util::ConvertTextureInputFormatToString(textureInputFormat).c_str(), pixels);
|
MG_Util::ConvertTextureInputFormatToString(textureInputFormat).c_str(), pixels);
|
||||||
// ===================== Error Checking ==============================
|
// ===================== Error Checking ==============================
|
||||||
if (!TextureImpl::ValidateTexturePixelDataType(texturePixelDataType)) return;
|
if (!TextureImpl::ValidateTexturePixelDataType(texturePixelDataType)) return;
|
||||||
@@ -502,14 +501,18 @@ namespace MobileGL {
|
|||||||
GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels) {
|
GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels) {
|
||||||
MGLOG_D(
|
MGLOG_D(
|
||||||
"%s called with target: %s, level: %d, internalformat: %s, width: %d, height: %d, depth: %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__,
|
"border: %d, format: %s, type: %s (%u), pixels: %p",
|
||||||
MG_Util::ConvertTextureUploadTargetToString(MG_Util::ConvertGLEnumToTextureUploadTarget(target)).c_str(),
|
__func__,
|
||||||
|
MG_Util::ConvertTextureUploadTargetToString(MG_Util::ConvertGLEnumToTextureUploadTarget(target))
|
||||||
|
.c_str(),
|
||||||
level,
|
level,
|
||||||
MG_Util::ConvertTextureInternalFormatToString(
|
MG_Util::ConvertTextureInternalFormatToString(
|
||||||
MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat)).c_str(),
|
MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat))
|
||||||
|
.c_str(),
|
||||||
width, height, depth, border,
|
width, height, depth, border,
|
||||||
MG_Util::ConvertTextureInputFormatToString(MG_Util::ConvertGLEnumToTextureInputFormat(format)).c_str(),
|
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);
|
type, pixels);
|
||||||
// ======================= Converting ================================
|
// ======================= Converting ================================
|
||||||
TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
|
TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
|
||||||
@@ -580,13 +583,13 @@ namespace MobileGL {
|
|||||||
reinterpret_cast<SizeT>(pixels);
|
reinterpret_cast<SizeT>(pixels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MOBILEGL_ASSERT(nullptr != dynamic_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get()),
|
MOBILEGL_ASSERT(nullptr != dynamic_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get()),
|
||||||
"Texture object here should always be an object with mipmap");
|
"Texture object here should always be an object with mipmap");
|
||||||
auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
|
auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
|
||||||
|
|
||||||
// Allocate in TextureObject
|
// Allocate in TextureObject
|
||||||
textureMipmapObject->AllocateStorage(textureUploadingTarget, level, {{width, height, depth}, internalBytes});
|
textureMipmapObject->AllocateStorage(textureUploadingTarget, level,
|
||||||
|
{{width, height, depth}, internalBytes});
|
||||||
|
|
||||||
if (!originalPixels) {
|
if (!originalPixels) {
|
||||||
MGLOG_D("%s: No input pixel and no PBO bound, no pixel transfer", __func__);
|
MGLOG_D("%s: No input pixel and no PBO bound, no pixel transfer", __func__);
|
||||||
@@ -601,8 +604,8 @@ namespace MobileGL {
|
|||||||
if (processedPixels && imageSize > 0) {
|
if (processedPixels && imageSize > 0) {
|
||||||
if (imageSize != internalBytes) {
|
if (imageSize != internalBytes) {
|
||||||
MGLOG_W("%s: Processed pixel data size (%zu) does not match expected size (%zu). "
|
MGLOG_W("%s: Processed pixel data size (%zu) does not match expected size (%zu). "
|
||||||
"This may indicate an alignment or processing issue.", __func__,
|
"This may indicate an alignment or processing issue.",
|
||||||
imageSize, internalBytes);
|
__func__, imageSize, internalBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
const SizeT copySize = std::min(imageSize, internalBytes);
|
const SizeT copySize = std::min(imageSize, internalBytes);
|
||||||
@@ -623,20 +626,16 @@ namespace MobileGL {
|
|||||||
TextureInputFormat textureInputFormat = MG_Util::ConvertGLEnumToTextureInputFormat(format);
|
TextureInputFormat textureInputFormat = MG_Util::ConvertGLEnumToTextureInputFormat(format);
|
||||||
TexturePixelDataType texturePixelDataType = MG_Util::ConvertGLEnumToTexturePixelDataType(type);
|
TexturePixelDataType texturePixelDataType = MG_Util::ConvertGLEnumToTexturePixelDataType(type);
|
||||||
TextureInternalFormat textureInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat);
|
TextureInternalFormat textureInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat);
|
||||||
MGLOG_D(
|
MGLOG_D("%s called with target: %s (%s), level: %d, internalformat: %s (%s), width: %d, height: %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",
|
||||||
"border: %d, format: %s (%s), type: %s (%s), pixels: %p", __func__,
|
__func__, MG_Util::ConvertTextureUploadTargetToString(textureUploadingTarget).c_str(),
|
||||||
MG_Util::ConvertTextureUploadTargetToString(textureUploadingTarget).c_str(),
|
MG_Util::ConvertGLEnumToString(target).c_str(), level,
|
||||||
MG_Util::ConvertGLEnumToString(target).c_str(),
|
|
||||||
level,
|
|
||||||
MG_Util::ConvertTextureInternalFormatToString(textureInternalFormat).c_str(),
|
MG_Util::ConvertTextureInternalFormatToString(textureInternalFormat).c_str(),
|
||||||
MG_Util::ConvertGLEnumToString(internalformat).c_str(),
|
MG_Util::ConvertGLEnumToString(internalformat).c_str(), width, height, border,
|
||||||
width, height, border,
|
|
||||||
MG_Util::ConvertTextureInputFormatToString(textureInputFormat).c_str(),
|
MG_Util::ConvertTextureInputFormatToString(textureInputFormat).c_str(),
|
||||||
MG_Util::ConvertGLEnumToString(format).c_str(),
|
MG_Util::ConvertGLEnumToString(format).c_str(),
|
||||||
MG_Util::ConvertTexturePixelDataTypeToString(texturePixelDataType).c_str(),
|
MG_Util::ConvertTexturePixelDataTypeToString(texturePixelDataType).c_str(),
|
||||||
MG_Util::ConvertGLEnumToString(type).c_str(),
|
MG_Util::ConvertGLEnumToString(type).c_str(), pixels);
|
||||||
pixels);
|
|
||||||
// ===================== Error Checking ==============================
|
// ===================== Error Checking ==============================
|
||||||
if (!TextureImpl::ValidateTexturePixelDataType(texturePixelDataType)) return;
|
if (!TextureImpl::ValidateTexturePixelDataType(texturePixelDataType)) return;
|
||||||
if (!TextureImpl::ValidateTextureInputFormat(textureInputFormat)) return;
|
if (!TextureImpl::ValidateTextureInputFormat(textureInputFormat)) return;
|
||||||
@@ -661,7 +660,8 @@ namespace MobileGL {
|
|||||||
// indicated by type.
|
// indicated by type.
|
||||||
|
|
||||||
// ======================= Processing ================================
|
// ======================= Processing ================================
|
||||||
textureInternalFormat = MG_Util::ConvertInternalFormatToSized(textureInternalFormat, textureInputFormat, texturePixelDataType);
|
textureInternalFormat =
|
||||||
|
MG_Util::ConvertInternalFormatToSized(textureInternalFormat, textureInputFormat, texturePixelDataType);
|
||||||
SharedPtr<MG_State::GLState::ITextureObject> textureObject = nullptr;
|
SharedPtr<MG_State::GLState::ITextureObject> textureObject = nullptr;
|
||||||
Bool isProxy = TextureImpl::IsProxyTextureTarget(textureUploadingTarget);
|
Bool isProxy = TextureImpl::IsProxyTextureTarget(textureUploadingTarget);
|
||||||
if (isProxy) {
|
if (isProxy) {
|
||||||
@@ -1229,7 +1229,8 @@ namespace MobileGL {
|
|||||||
void CopyTexImage2D_State(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width,
|
void CopyTexImage2D_State(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width,
|
||||||
GLsizei height, GLint border) {
|
GLsizei height, GLint border) {
|
||||||
GLenum outInternalFormat, format, type;
|
GLenum outInternalFormat, format, type;
|
||||||
MG_Util::TextureFormatProcessor::NormalizePixelFormat(internalformat, 0, &outInternalFormat, &format, &type);
|
MG_Util::TextureFormatProcessor::NormalizePixelFormat(internalformat, 0, &outInternalFormat, &format,
|
||||||
|
&type);
|
||||||
const auto pixelUnpackBufferObject =
|
const auto pixelUnpackBufferObject =
|
||||||
MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelUnpack).GetBoundObject();
|
MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelUnpack).GetBoundObject();
|
||||||
TexImage2D_State(target, level, outInternalFormat, width, height, border, format, type, nullptr);
|
TexImage2D_State(target, level, outInternalFormat, width, height, border, format, type, nullptr);
|
||||||
|
|||||||
@@ -170,7 +170,8 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
Bool ValidateTextureInternalFormatCompatibleWithInput(TextureInputFormat format, TextureInternalFormat internalFormat,
|
Bool ValidateTextureInternalFormatCompatibleWithInput(TextureInputFormat format,
|
||||||
|
TextureInternalFormat internalFormat,
|
||||||
TexturePixelDataType type) {
|
TexturePixelDataType type) {
|
||||||
if (type == TexturePixelDataType::UnsignedByte332 || type == TexturePixelDataType::UnsignedByte233Rev ||
|
if (type == TexturePixelDataType::UnsignedByte332 || type == TexturePixelDataType::UnsignedByte233Rev ||
|
||||||
type == TexturePixelDataType::UnsignedShort565 || type == TexturePixelDataType::UnsignedShort565Rev ||
|
type == TexturePixelDataType::UnsignedShort565 || type == TexturePixelDataType::UnsignedShort565Rev ||
|
||||||
@@ -178,7 +179,8 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
if (format != TextureInputFormat::RGB) {
|
if (format != TextureInputFormat::RGB) {
|
||||||
MG_State::pGLContext->RecordError(
|
MG_State::pGLContext->RecordError(
|
||||||
ErrorCode::InvalidOperation,
|
ErrorCode::InvalidOperation,
|
||||||
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureInternalFormatCompatibleWithInput",
|
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl",
|
||||||
|
"ValidateTextureInternalFormatCompatibleWithInput",
|
||||||
"Invalid format for the given type"));
|
"Invalid format for the given type"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -193,7 +195,8 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
if (format != TextureInputFormat::RGBA && format != TextureInputFormat::BGRA) {
|
if (format != TextureInputFormat::RGBA && format != TextureInputFormat::BGRA) {
|
||||||
MG_State::pGLContext->RecordError(
|
MG_State::pGLContext->RecordError(
|
||||||
ErrorCode::InvalidOperation,
|
ErrorCode::InvalidOperation,
|
||||||
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureInternalFormatCompatibleWithInput",
|
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl",
|
||||||
|
"ValidateTextureInternalFormatCompatibleWithInput",
|
||||||
"Invalid format for the given type"));
|
"Invalid format for the given type"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -206,7 +209,8 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
if (format != TextureInputFormat::DepthComponent) {
|
if (format != TextureInputFormat::DepthComponent) {
|
||||||
MG_State::pGLContext->RecordError(
|
MG_State::pGLContext->RecordError(
|
||||||
ErrorCode::InvalidOperation,
|
ErrorCode::InvalidOperation,
|
||||||
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureInternalFormatCompatibleWithInput",
|
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl",
|
||||||
|
"ValidateTextureInternalFormatCompatibleWithInput",
|
||||||
"Invalid format for depth component internal format"));
|
"Invalid format for depth component internal format"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
Bool ValidateTextureSizeRange(SizeT width, SizeT height, SizeT depth);
|
Bool ValidateTextureSizeRange(SizeT width, SizeT height, SizeT depth);
|
||||||
Bool ValidateTextureInternalFormat(TextureInternalFormat format);
|
Bool ValidateTextureInternalFormat(TextureInternalFormat format);
|
||||||
Bool ValidateTextureBorderNumber(Int border);
|
Bool ValidateTextureBorderNumber(Int border);
|
||||||
Bool ValidateTextureInternalFormatCompatibleWithInput(TextureInputFormat format, TextureInternalFormat internalFormat,
|
Bool ValidateTextureInternalFormatCompatibleWithInput(TextureInputFormat format,
|
||||||
|
TextureInternalFormat internalFormat,
|
||||||
TexturePixelDataType type);
|
TexturePixelDataType type);
|
||||||
Bool ValidateTextureLevelWithUploadTarget(TextureUploadTarget target, Int level);
|
Bool ValidateTextureLevelWithUploadTarget(TextureUploadTarget target, Int level);
|
||||||
Bool ValidateTextureObject(SharedPtr<MG_State::GLState::ITextureObject> textureObject);
|
Bool ValidateTextureObject(SharedPtr<MG_State::GLState::ITextureObject> textureObject);
|
||||||
|
|||||||
@@ -14,14 +14,18 @@ namespace MobileGL {
|
|||||||
namespace GLState {
|
namespace GLState {
|
||||||
BufferObject::BufferObject(Uint externalIndex)
|
BufferObject::BufferObject(Uint externalIndex)
|
||||||
: m_externalIndex(externalIndex), m_size(0), m_usage(BufferUsage::StaticDraw), m_isMapped(false),
|
: 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_mappingAccess(BufferMappingAccessBit::Null),
|
||||||
m_dataPtr(MakeShared<Data>()) {}
|
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) {
|
void BufferObject::Resize(SizeT size) {
|
||||||
m_size = size;
|
m_size = size;
|
||||||
m_dataPtr->reserve(std::bit_ceil(size)); // power-of-2 reserve
|
m_dataPtr->reserve(std::bit_ceil(size)); // power-of-2 reserve
|
||||||
m_dataPtr->resize(size);
|
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) {
|
void BufferObject::UploadData(DataPtr data, SizeT atOffset) {
|
||||||
@@ -30,7 +34,14 @@ namespace MobileGL {
|
|||||||
data.size, m_size);
|
data.size, m_size);
|
||||||
MOBILEGL_ASSERT(!m_isMapped, "Cannot upload data while buffer is mapped.");
|
MOBILEGL_ASSERT(!m_isMapped, "Cannot upload data while buffer is mapped.");
|
||||||
Memcpy(m_dataPtr->data() + atOffset, data.data, data.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;
|
||||||
|
// 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) {
|
void BufferObject::SetUsage(BufferUsage usage) {
|
||||||
@@ -44,7 +55,8 @@ namespace MobileGL {
|
|||||||
if (!(m_mappingAccess & BufferMappingAccessBit::FlushExplicit)) { // if we didn't flush explicitly
|
if (!(m_mappingAccess & BufferMappingAccessBit::FlushExplicit)) { // if we didn't flush explicitly
|
||||||
Memcpy(m_dataPtr->data() + m_mappedRange.start, m_stagingData.data(),
|
Memcpy(m_dataPtr->data() + m_mappedRange.start, m_stagingData.data(),
|
||||||
m_mappedRange.end - m_mappedRange.start);
|
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();
|
m_stagingData.clear();
|
||||||
@@ -69,7 +81,8 @@ namespace MobileGL {
|
|||||||
"Flush range out of bounds: mappedRange.end (%zu) < end (%zu)", m_mappedRange.end, end);
|
"Flush range out of bounds: mappedRange.end (%zu) < end (%zu)", m_mappedRange.end, end);
|
||||||
|
|
||||||
Memcpy(m_dataPtr->data() + start, m_stagingData.data() + offset, length);
|
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) {
|
void BufferObject::UploadSubData(DataPtr data, SizeT atOffset) {
|
||||||
@@ -79,7 +92,10 @@ namespace MobileGL {
|
|||||||
atOffset, data.size, m_size);
|
atOffset, data.size, m_size);
|
||||||
|
|
||||||
Memcpy(m_dataPtr->data() + atOffset, data.data, data.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,
|
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;
|
const Uint8* srcData = src->m_dataPtr->data() + srcOffset;
|
||||||
Memcpy(m_dataPtr->data() + dstOffset, srcData, size);
|
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) {
|
void* BufferObject::AcquireMemory(Bool markMapped, Bool read, Bool write) {
|
||||||
@@ -144,6 +161,14 @@ namespace MobileGL {
|
|||||||
m_ownsStagingData = false;
|
m_ownsStagingData = false;
|
||||||
return m_dataPtr->data() + range.start;
|
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 {
|
const SharedPtr<Data> BufferObject::GetDataReadOnly() const {
|
||||||
@@ -151,7 +176,8 @@ namespace MobileGL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BufferObject::ClearDirty() {
|
void BufferObject::ClearDirty() {
|
||||||
m_dirtyRange = {0, 0};
|
m_change.DirtyRanges.clear();
|
||||||
|
m_change.Bits = BufferChangeBits::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
SizeT BufferObject::GetSize() const {
|
SizeT BufferObject::GetSize() const {
|
||||||
@@ -162,8 +188,12 @@ namespace MobileGL {
|
|||||||
return m_usage;
|
return m_usage;
|
||||||
}
|
}
|
||||||
|
|
||||||
Range1D BufferObject::GetDirtyRange() const {
|
const VecRange1D& BufferObject::GetDirtyRanges() const {
|
||||||
return m_dirtyRange;
|
return m_change.DirtyRanges;
|
||||||
|
}
|
||||||
|
|
||||||
|
Flags<BufferChangeBits> BufferObject::GetChangeBits() const {
|
||||||
|
return m_change.Bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bool BufferObject::IsMapped() const {
|
Bool BufferObject::IsMapped() const {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "MG_Util/Types.h"
|
#include "MG_Util/Types.h"
|
||||||
#include <Includes.h>
|
#include <Includes.h>
|
||||||
|
#include <MG_Util/Math/VectorTypes.h>
|
||||||
|
|
||||||
namespace MobileGL {
|
namespace MobileGL {
|
||||||
enum class BufferTarget {
|
enum class BufferTarget {
|
||||||
@@ -55,6 +56,23 @@ namespace MobileGL {
|
|||||||
Coherent = 0x80
|
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 MG_State {
|
||||||
namespace GLState {
|
namespace GLState {
|
||||||
class BufferObject {
|
class BufferObject {
|
||||||
@@ -77,11 +95,12 @@ namespace MobileGL {
|
|||||||
Bool IsMapped() const;
|
Bool IsMapped() const;
|
||||||
SizeT GetSize() const;
|
SizeT GetSize() const;
|
||||||
BufferUsage GetUsage() const;
|
BufferUsage GetUsage() const;
|
||||||
Range1D GetDirtyRange() const;
|
|
||||||
Range1D GetMappedRange() const;
|
Range1D GetMappedRange() const;
|
||||||
const SharedPtr<Data> GetDataReadOnly() const;
|
const SharedPtr<Data> GetDataReadOnly() const;
|
||||||
Flags<BufferMappingAccessBit> GetMappingAccess() const;
|
Flags<BufferMappingAccessBit> GetMappingAccess() const;
|
||||||
Uint GetExternalIndex() const;
|
Uint GetExternalIndex() const;
|
||||||
|
const VecRange1D& GetDirtyRanges() const;
|
||||||
|
Flags<BufferChangeBits> GetChangeBits() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Uint m_externalIndex = 0;
|
const Uint m_externalIndex = 0;
|
||||||
@@ -90,7 +109,7 @@ namespace MobileGL {
|
|||||||
SharedPtr<Data> m_dataPtr;
|
SharedPtr<Data> m_dataPtr;
|
||||||
Bool m_isMapped;
|
Bool m_isMapped;
|
||||||
Flags<BufferMappingAccessBit> m_mappingAccess;
|
Flags<BufferMappingAccessBit> m_mappingAccess;
|
||||||
Range1D m_dirtyRange;
|
BufferChange m_change;
|
||||||
Range1D m_mappedRange;
|
Range1D m_mappedRange;
|
||||||
Vector<Uint8> m_stagingData;
|
Vector<Uint8> m_stagingData;
|
||||||
Bool m_ownsStagingData;
|
Bool m_ownsStagingData;
|
||||||
|
|||||||
@@ -42,7 +42,8 @@ namespace MobileGL {
|
|||||||
} else {
|
} else {
|
||||||
m_compileStatus = false;
|
m_compileStatus = false;
|
||||||
m_infoLog = result.error().log;
|
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());
|
m_externalIndex, m_source.c_str(), m_infoLog.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ namespace MobileGL {
|
|||||||
SizeT GetByteSize(Uint level) const;
|
SizeT GetByteSize(Uint level) const;
|
||||||
void MarkDirty(Uint level, bool dirty);
|
void MarkDirty(Uint level, bool dirty);
|
||||||
bool IsDirty(Uint level) const;
|
bool IsDirty(Uint level) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Vector<IntVec3> m_texelSizes;
|
Vector<IntVec3> m_texelSizes;
|
||||||
Vector<Vector<Uint8>> m_data;
|
Vector<Vector<Uint8>> m_data;
|
||||||
|
|||||||
@@ -19,7 +19,9 @@ namespace MobileGL {
|
|||||||
template <SizeT TargetCount>
|
template <SizeT TargetCount>
|
||||||
class MipmapUploadTargetArray {
|
class MipmapUploadTargetArray {
|
||||||
public:
|
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) {
|
void AllocateLevel(Uint targetIndex, Uint level, MipmapInput input) {
|
||||||
MOBILEGL_ASSERT(targetIndex < TargetCount, "AllocateLevel: target invalid");
|
MOBILEGL_ASSERT(targetIndex < TargetCount, "AllocateLevel: target invalid");
|
||||||
|
|||||||
@@ -81,7 +81,8 @@ namespace MobileGL {
|
|||||||
|
|
||||||
class TextureObjectMipmap : public TextureObjectBase {
|
class TextureObjectMipmap : public TextureObjectBase {
|
||||||
public:
|
public:
|
||||||
TextureObjectMipmap(TextureTarget target, Uint externalIndex): TextureObjectBase(target, externalIndex) {}
|
TextureObjectMipmap(TextureTarget target, Uint externalIndex)
|
||||||
|
: TextureObjectBase(target, externalIndex) {}
|
||||||
|
|
||||||
TextureStorageType GetStorageType() const override { return TextureStorageType::Mipmap; }
|
TextureStorageType GetStorageType() const override { return TextureStorageType::Mipmap; }
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ namespace MobileGL {
|
|||||||
TextureStorageType GetStorageType() const override { return TextureStorageType::Buffer; }
|
TextureStorageType GetStorageType() const override { return TextureStorageType::Buffer; }
|
||||||
explicit TextureObjectBuffer(Uint externalIndex);
|
explicit TextureObjectBuffer(Uint externalIndex);
|
||||||
const Vector<TextureUploadTarget>& GetUploadTargets() const override { return m_uploadTargets; }
|
const Vector<TextureUploadTarget>& GetUploadTargets() const override { return m_uploadTargets; }
|
||||||
BindingSlot<BufferObject>& GetBufferBindingSlot(TextureUploadTarget target = TextureUploadTarget::TextureBuffer);
|
BindingSlot<BufferObject>& GetBufferBindingSlot(
|
||||||
|
TextureUploadTarget target = TextureUploadTarget::TextureBuffer);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const override;
|
Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const override;
|
||||||
|
|||||||
@@ -457,7 +457,10 @@ namespace MobileGL {
|
|||||||
void *libGLES = nullptr, *libEGL = nullptr;
|
void *libGLES = nullptr, *libEGL = nullptr;
|
||||||
|
|
||||||
static const char* LibPathPrefixes[] = {
|
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
|
"", // We should put this to the end of the list to avoid breaking `LD_LIBRARY_PATH` usage
|
||||||
nullptr};
|
nullptr};
|
||||||
static const char* LibExts[] = {"so", "so.1", "so.2", "dylib", "dll", nullptr};
|
static const char* LibExts[] = {"so", "so.1", "so.2", "dylib", "dll", nullptr};
|
||||||
@@ -531,8 +534,10 @@ namespace MobileGL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MGLOG_I("OpenGL ES capabilities:");
|
MGLOG_I("OpenGL ES capabilities:");
|
||||||
MG_External::GLES::glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &MG_External::GLES::g_glesCaps.uniformBufferOffsetAlignment);
|
MG_External::GLES::glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT,
|
||||||
MGLOG_I(" GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: %d", MG_External::GLES::g_glesCaps.uniformBufferOffsetAlignment);
|
&MG_External::GLES::g_glesCaps.uniformBufferOffsetAlignment);
|
||||||
|
MGLOG_I(" GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: %d",
|
||||||
|
MG_External::GLES::g_glesCaps.uniformBufferOffsetAlignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitGLES() {
|
void InitGLES() {
|
||||||
|
|||||||
@@ -514,13 +514,15 @@ namespace MobileGL {
|
|||||||
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 EGLBoolean (*eglDestroySync_PTR)(EGLDisplay dpy, EGLSync sync);
|
||||||
typedef EGLint (*eglClientWaitSync_PTR)(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout);
|
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 EGLBoolean (*eglGetSyncAttrib_PTR)(EGLDisplay dpy, EGLSync sync, EGLint attribute,
|
||||||
typedef EGLImage (*eglCreateImage_PTR)(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib * attrib_list);
|
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 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);
|
typedef EGLBoolean (*eglWaitSync_PTR)(EGLDisplay dpy, EGLSync sync, EGLint flags);
|
||||||
|
|
||||||
|
|
||||||
EGL_FUNC_DECL(eglBindAPI)
|
EGL_FUNC_DECL(eglBindAPI)
|
||||||
EGL_FUNC_DECL(eglBindTexImage)
|
EGL_FUNC_DECL(eglBindTexImage)
|
||||||
EGL_FUNC_DECL(eglChooseConfig)
|
EGL_FUNC_DECL(eglChooseConfig)
|
||||||
|
|||||||
@@ -234,7 +234,8 @@ namespace MobileGL {
|
|||||||
case GL_RGBA:
|
case GL_RGBA:
|
||||||
return TextureInternalFormat::RGBA;
|
return TextureInternalFormat::RGBA;
|
||||||
default:
|
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;
|
return TextureInternalFormat::Unknown;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,8 @@ namespace MobileGL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureInternalFormat ConvertInternalFormatToSized(TextureInternalFormat internalformat, TextureInputFormat format, TexturePixelDataType type) {
|
TextureInternalFormat ConvertInternalFormatToSized(TextureInternalFormat internalformat,
|
||||||
|
TextureInputFormat format, TexturePixelDataType type) {
|
||||||
switch (internalformat) {
|
switch (internalformat) {
|
||||||
case TextureInternalFormat::R8:
|
case TextureInternalFormat::R8:
|
||||||
case TextureInternalFormat::R8Snorm:
|
case TextureInternalFormat::R8Snorm:
|
||||||
@@ -131,9 +132,9 @@ namespace MobileGL {
|
|||||||
case TexturePixelDataType::UnsignedShort:
|
case TexturePixelDataType::UnsignedShort:
|
||||||
return TextureInternalFormat::RGBA16;
|
return TextureInternalFormat::RGBA16;
|
||||||
default:
|
default:
|
||||||
MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, returning original.",
|
MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, "
|
||||||
__func__,
|
"returning original.",
|
||||||
MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(),
|
__func__, MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(),
|
||||||
MG_Util::ConvertTextureInputFormatToString(format).c_str(),
|
MG_Util::ConvertTextureInputFormatToString(format).c_str(),
|
||||||
MG_Util::ConvertTexturePixelDataTypeToString(type).c_str());
|
MG_Util::ConvertTexturePixelDataTypeToString(type).c_str());
|
||||||
return internalformat;
|
return internalformat;
|
||||||
@@ -144,9 +145,9 @@ namespace MobileGL {
|
|||||||
case TexturePixelDataType::UnsignedByte:
|
case TexturePixelDataType::UnsignedByte:
|
||||||
return TextureInternalFormat::RGB8;
|
return TextureInternalFormat::RGB8;
|
||||||
default:
|
default:
|
||||||
MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, returning original.",
|
MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, "
|
||||||
__func__,
|
"returning original.",
|
||||||
MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(),
|
__func__, MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(),
|
||||||
MG_Util::ConvertTextureInputFormatToString(format).c_str(),
|
MG_Util::ConvertTextureInputFormatToString(format).c_str(),
|
||||||
MG_Util::ConvertTexturePixelDataTypeToString(type).c_str());
|
MG_Util::ConvertTexturePixelDataTypeToString(type).c_str());
|
||||||
return internalformat;
|
return internalformat;
|
||||||
@@ -159,9 +160,9 @@ namespace MobileGL {
|
|||||||
case TexturePixelDataType::UnsignedShort:
|
case TexturePixelDataType::UnsignedShort:
|
||||||
return TextureInternalFormat::RG16;
|
return TextureInternalFormat::RG16;
|
||||||
default:
|
default:
|
||||||
MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, returning original.",
|
MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, "
|
||||||
__func__,
|
"returning original.",
|
||||||
MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(),
|
__func__, MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(),
|
||||||
MG_Util::ConvertTextureInputFormatToString(format).c_str(),
|
MG_Util::ConvertTextureInputFormatToString(format).c_str(),
|
||||||
MG_Util::ConvertTexturePixelDataTypeToString(type).c_str());
|
MG_Util::ConvertTexturePixelDataTypeToString(type).c_str());
|
||||||
return internalformat;
|
return internalformat;
|
||||||
@@ -174,18 +175,18 @@ namespace MobileGL {
|
|||||||
case TexturePixelDataType::UnsignedShort:
|
case TexturePixelDataType::UnsignedShort:
|
||||||
return TextureInternalFormat::R16;
|
return TextureInternalFormat::R16;
|
||||||
default:
|
default:
|
||||||
MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, returning original.",
|
MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, "
|
||||||
__func__,
|
"returning original.",
|
||||||
MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(),
|
__func__, MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(),
|
||||||
MG_Util::ConvertTextureInputFormatToString(format).c_str(),
|
MG_Util::ConvertTextureInputFormatToString(format).c_str(),
|
||||||
MG_Util::ConvertTexturePixelDataTypeToString(type).c_str());
|
MG_Util::ConvertTexturePixelDataTypeToString(type).c_str());
|
||||||
return internalformat;
|
return internalformat;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, returning original.",
|
MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, returning "
|
||||||
__func__,
|
"original.",
|
||||||
MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(),
|
__func__, MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(),
|
||||||
MG_Util::ConvertTextureInputFormatToString(format).c_str(),
|
MG_Util::ConvertTextureInputFormatToString(format).c_str(),
|
||||||
MG_Util::ConvertTexturePixelDataTypeToString(type).c_str());
|
MG_Util::ConvertTexturePixelDataTypeToString(type).c_str());
|
||||||
return internalformat;
|
return internalformat;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
namespace MobileGL {
|
namespace MobileGL {
|
||||||
namespace MG_Util {
|
namespace MG_Util {
|
||||||
TextureTarget ConvertTextureUploadTargetToTextureTarget(TextureUploadTarget target);
|
TextureTarget ConvertTextureUploadTargetToTextureTarget(TextureUploadTarget target);
|
||||||
TextureInternalFormat ConvertInternalFormatToSized(TextureInternalFormat internalformat, TextureInputFormat format, TexturePixelDataType type);
|
TextureInternalFormat ConvertInternalFormatToSized(TextureInternalFormat internalformat,
|
||||||
|
TextureInputFormat format, TexturePixelDataType type);
|
||||||
} // namespace MG_Util
|
} // namespace MG_Util
|
||||||
} // namespace MobileGL
|
} // namespace MobileGL
|
||||||
@@ -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,7 +11,6 @@
|
|||||||
#include <Includes.h>
|
#include <Includes.h>
|
||||||
|
|
||||||
namespace MobileGL {
|
namespace MobileGL {
|
||||||
|
|
||||||
template <typename Derived, typename T, SizeT N>
|
template <typename Derived, typename T, SizeT N>
|
||||||
struct VecBase {
|
struct VecBase {
|
||||||
Array<T, N> data;
|
Array<T, N> data;
|
||||||
@@ -247,4 +246,15 @@ namespace MobileGL {
|
|||||||
return incident - normal * (2.0f * incident.Dot(normal));
|
return incident - normal * (2.0f * incident.Dot(normal));
|
||||||
}
|
}
|
||||||
} // namespace MG_Util
|
} // 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
|
} // namespace MobileGL
|
||||||
@@ -227,13 +227,12 @@ namespace MobileGL {
|
|||||||
return allSpirv;
|
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;
|
using namespace spvtools;
|
||||||
Optimizer optimizer(SPV_ENV_UNIVERSAL_1_5);
|
Optimizer optimizer(SPV_ENV_UNIVERSAL_1_5);
|
||||||
|
|
||||||
optimizer
|
optimizer.RegisterPass(EliminateFloatEqualsZeroPass::CreateEliminateFloatEqualsZeroPass());
|
||||||
.RegisterPass(EliminateFloatEqualsZeroPass::CreateEliminateFloatEqualsZeroPass())
|
|
||||||
;
|
|
||||||
|
|
||||||
return optimizer.Run(inputBinary.data(), inputBinary.size(), &outputBinary);
|
return optimizer.Run(inputBinary.data(), inputBinary.size(), &outputBinary);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ namespace MobileGL {
|
|||||||
static Result<SharedPtr<glslang::TShader>> CompileShader(const ShaderAttrib& attrib);
|
static Result<SharedPtr<glslang::TShader>> CompileShader(const ShaderAttrib& attrib);
|
||||||
static Result<SharedPtr<glslang::TProgram>> LinkProgram(const ProgramAttrib& attrib);
|
static Result<SharedPtr<glslang::TProgram>> LinkProgram(const ProgramAttrib& attrib);
|
||||||
static Result<Vector<Vector<unsigned>>> GetSpirvBinaryFromProgram(const ProgramBinaryAttrib& 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);
|
static Result<String> DecompileShader(SpvcSession& session);
|
||||||
};
|
};
|
||||||
} // namespace ShaderTranspiler
|
} // 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
|
// Copyright (c) 2025-2026 MobileGL-Dev
|
||||||
// Licensed under the GNU Lesser General Public License v3.0:
|
// Licensed under the GNU Lesser General Public License v3.0:
|
||||||
// https://www.gnu.org/licenses/gpl-3.0.txt
|
// https://www.gnu.org/licenses/gpl-3.0.txt
|
||||||
@@ -96,18 +96,13 @@ namespace MobileGL {
|
|||||||
|
|
||||||
// 2. Create constant ID for `Epsilon`
|
// 2. Create constant ID for `Epsilon`
|
||||||
const analysis::Constant* eps_const = const_mgr->GetConstant(
|
const analysis::Constant* eps_const = const_mgr->GetConstant(
|
||||||
type_mgr->GetType(float_type_id),
|
type_mgr->GetType(float_type_id), {*(reinterpret_cast<const uint32_t*>(&K_EPSILON))});
|
||||||
{*(reinterpret_cast<const uint32_t*>(&K_EPSILON))}
|
|
||||||
);
|
|
||||||
uint32_t eps_id = const_mgr->GetDefiningInstruction(eps_const)->result_id();
|
uint32_t eps_id = const_mgr->GetDefiningInstruction(eps_const)->result_id();
|
||||||
|
|
||||||
// 3. Build Abs(x) inst
|
// 3. Build Abs(x) inst
|
||||||
// OpExtInst %float_type %glsl_import Abs %x
|
// OpExtInst %float_type %glsl_import Abs %x
|
||||||
InstructionBuilder builder(
|
InstructionBuilder builder(
|
||||||
context(),
|
context(), &inst, IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
|
||||||
&inst,
|
|
||||||
IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping
|
|
||||||
);
|
|
||||||
|
|
||||||
std::vector<Operand> abs_operands;
|
std::vector<Operand> abs_operands;
|
||||||
abs_operands.push_back({SPV_OPERAND_TYPE_ID, {glsl_std_450_id}});
|
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
|
// In GLSL.std.450, `FAbs`'s OpCode == 4
|
||||||
// Ref: https://registry.khronos.org/SPIR-V/specs/1.0/GLSL.std.450.html
|
// Ref: https://registry.khronos.org/SPIR-V/specs/1.0/GLSL.std.450.html
|
||||||
Instruction* abs_inst = builder.AddInstruction(MakeUnique<Instruction>(
|
Instruction* abs_inst = builder.AddInstruction(MakeUnique<Instruction>(
|
||||||
context(),
|
context(), spv::Op::OpExtInst, float_type_id, context()->TakeNextId(), abs_operands));
|
||||||
spv::Op::OpExtInst,
|
|
||||||
float_type_id,
|
|
||||||
context()->TakeNextId(),
|
|
||||||
abs_operands
|
|
||||||
));
|
|
||||||
|
|
||||||
// 4. build Abs(x) < Epsilon
|
// 4. build Abs(x) < Epsilon
|
||||||
// OpFOrdLessThan %bool_type %abs_val %eps
|
// 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, {abs_inst->result_id()}});
|
||||||
less_operands.push_back({SPV_OPERAND_TYPE_ID, {eps_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>(
|
Instruction* less_than_inst = builder.AddInstruction(MakeUnique<Instruction>(
|
||||||
context(),
|
context(), isEqualOp ? spv::Op::OpFOrdLessThan : spv::Op::OpFOrdGreaterThanEqual,
|
||||||
isEqualOp ? spv::Op::OpFOrdLessThan : spv::Op::OpFOrdGreaterThanEqual,
|
bool_type_id, context()->TakeNextId(), less_operands));
|
||||||
bool_type_id,
|
|
||||||
context()->TakeNextId(),
|
|
||||||
less_operands
|
|
||||||
));
|
|
||||||
|
|
||||||
// 5. Replaces all uses of old insn with new one
|
// 5. Replaces all uses of old insn with new one
|
||||||
context()->ReplaceAllUsesWith(inst.result_id(), less_than_inst->result_id());
|
context()->ReplaceAllUsesWith(inst.result_id(), less_than_inst->result_id());
|
||||||
@@ -161,5 +148,5 @@ namespace MobileGL {
|
|||||||
return spvtools::Optimizer::PassToken(MakeUnique<EliminateFloatEqualsZeroPass>());
|
return spvtools::Optimizer::PassToken(MakeUnique<EliminateFloatEqualsZeroPass>());
|
||||||
}
|
}
|
||||||
} // namespace ShaderTranspiler
|
} // 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
|
// Copyright (c) 2025-2026 MobileGL-Dev
|
||||||
// Licensed under the GNU Lesser General Public License v3.0:
|
// Licensed under the GNU Lesser General Public License v3.0:
|
||||||
// https://www.gnu.org/licenses/gpl-3.0.txt
|
// https://www.gnu.org/licenses/gpl-3.0.txt
|
||||||
@@ -21,10 +21,10 @@ namespace MobileGL {
|
|||||||
Status Process() override;
|
Status Process() override;
|
||||||
|
|
||||||
static spvtools::Optimizer::PassToken CreateEliminateFloatEqualsZeroPass();
|
static spvtools::Optimizer::PassToken CreateEliminateFloatEqualsZeroPass();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const float K_EPSILON = 0.0001f;
|
const float K_EPSILON = 0.0001f;
|
||||||
};
|
};
|
||||||
} // namespace ShaderTranspiler
|
} // namespace ShaderTranspiler
|
||||||
} // namespace MG_Util
|
} // namespace MG_Util
|
||||||
} // namespace MobileGL
|
} // namespace MobileGL
|
||||||
|
|
||||||
|
|||||||
@@ -108,8 +108,8 @@ namespace MobileGL::MG_Util::PixelStoreProcessor {
|
|||||||
const Int copyHeight = height;
|
const Int copyHeight = height;
|
||||||
const Int copyDepth = depth;
|
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__,
|
MGLOG_D("%s: start at: (%d, %d, %d), copy size: (%d, %d, %d), i/o row stride: (%d, %dx%d)", __func__, startX,
|
||||||
startX, startY, startZ, copyWidth, copyHeight, copyDepth, inputRowStride, width, pixelSize);
|
startY, startZ, copyWidth, copyHeight, copyDepth, inputRowStride, width, pixelSize);
|
||||||
|
|
||||||
if (copyWidth <= 0 || copyHeight <= 0 || copyDepth <= 0) {
|
if (copyWidth <= 0 || copyHeight <= 0 || copyDepth <= 0) {
|
||||||
outSize = 0;
|
outSize = 0;
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
|
|
||||||
namespace MobileGL::MG_Util::PixelStoreProcessor {
|
namespace MobileGL::MG_Util::PixelStoreProcessor {
|
||||||
void* ProcessTexturePixelsDataUnpack(const void* inputPixels, const PixelStoreParameters& params,
|
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);
|
IntVec3 dimension, Bool isBitmap, SizeT& outSize);
|
||||||
void* ProcessTexturePixelsDataPack(const void* inputPixels, const PixelStoreParameters& params, SizeT pixelSize,
|
void* ProcessTexturePixelsDataPack(const void* inputPixels, const PixelStoreParameters& params, SizeT pixelSize,
|
||||||
IntVec3 dimension, Bool isBitmap, SizeT& outSize);
|
IntVec3 dimension, Bool isBitmap, SizeT& outSize);
|
||||||
|
|||||||
@@ -10,7 +10,8 @@
|
|||||||
#include "MG_Util/Converters/GLToStr/GLEnumConverter.h"
|
#include "MG_Util/Converters/GLToStr/GLEnumConverter.h"
|
||||||
|
|
||||||
namespace MobileGL::MG_Util::TextureFormatProcessor {
|
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
|
#ifdef TRACY_ENABLE
|
||||||
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
|
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
|
||||||
#endif
|
#endif
|
||||||
@@ -183,7 +184,8 @@ namespace MobileGL::MG_Util::TextureFormatProcessor {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
MGLOG_E("NormalizePixelFormat: outFormat: unhandled internalFormat: %s", MG_Util::ConvertGLEnumToString(internalFormat).c_str());
|
MGLOG_E("NormalizePixelFormat: outFormat: unhandled internalFormat: %s",
|
||||||
|
MG_Util::ConvertGLEnumToString(internalFormat).c_str());
|
||||||
// Fallback handling for other formats
|
// Fallback handling for other formats
|
||||||
// Try to infer format from internal format name
|
// Try to infer format from internal format name
|
||||||
if (strstr(MG_Util::ConvertGLEnumToString(internalFormat).c_str(), "RGBA") != nullptr) {
|
if (strstr(MG_Util::ConvertGLEnumToString(internalFormat).c_str(), "RGBA") != nullptr) {
|
||||||
@@ -335,7 +337,8 @@ namespace MobileGL::MG_Util::TextureFormatProcessor {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
MGLOG_E("NormalizePixelFormat: outType: unhandled internalFormat: %s", MG_Util::ConvertGLEnumToString(internalFormat).c_str());
|
MGLOG_E("NormalizePixelFormat: outType: unhandled internalFormat: %s",
|
||||||
|
MG_Util::ConvertGLEnumToString(internalFormat).c_str());
|
||||||
// Fallback handling for other formats
|
// Fallback handling for other formats
|
||||||
*outType = GL_UNSIGNED_BYTE;
|
*outType = GL_UNSIGNED_BYTE;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -14,5 +14,6 @@ namespace MobileGL::MG_Util::TextureFormatProcessor {
|
|||||||
NoNorm16 = 1 << 0,
|
NoNorm16 = 1 << 0,
|
||||||
None = 0,
|
None = 0,
|
||||||
};
|
};
|
||||||
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);
|
||||||
} // namespace MobileGL::MG_Util::TextureFormatProcessor
|
} // namespace MobileGL::MG_Util::TextureFormatProcessor
|
||||||
Reference in New Issue
Block a user