Merge pull request #9 from BZLZHH/Agent/CodexAudit

This commit is contained in:
2026-06-10 12:33:01 +08:00
committed by GitHub
104 changed files with 7397 additions and 1047 deletions
+1 -1
View File
@@ -35,7 +35,7 @@
// ====================== MobileGL configurations ======================= // // ====================== MobileGL configurations ======================= //
#ifndef MOBILEGL_LOG_ACTIVE_LEVEL #ifndef MOBILEGL_LOG_ACTIVE_LEVEL
#define MOBILEGL_LOG_ACTIVE_LEVEL MOBILEGL_LOG_LEVEL_DEBUG #define MOBILEGL_LOG_ACTIVE_LEVEL MOBILEGL_LOG_LEVEL_INFO
#endif #endif
#define MOBILEGL_LOG_ENABLE_CONSOLE 0 #define MOBILEGL_LOG_ENABLE_CONSOLE 0
+17
View File
@@ -15,7 +15,16 @@
#include <MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h> #include <MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h>
namespace MobileGL { namespace MobileGL {
namespace {
Bool g_isInitialized = false;
}
void Initialize() { void Initialize() {
if (g_isInitialized) {
MGLOG_D("MobileGL already initialized; skipping duplicate Initialize()");
return;
}
MG_Util::Debug::InitFile(); MG_Util::Debug::InitFile();
MGLOG_I("Initializing MobileGL..."); MGLOG_I("Initializing MobileGL...");
MG_ConfigLoader::Init(); MG_ConfigLoader::Init();
@@ -28,16 +37,24 @@ namespace MobileGL {
MGLOG_D("MG_Impl initialized"); MGLOG_D("MG_Impl initialized");
glslang::InitializeProcess(); glslang::InitializeProcess();
MGLOG_D("glslang initialized"); MGLOG_D("glslang initialized");
g_isInitialized = true;
MGLOG_I("MobileGL initialized"); MGLOG_I("MobileGL initialized");
} }
void Destroy() { void Destroy() {
if (!g_isInitialized) {
return;
}
MGLOG_I("MobileGL closing..."); MGLOG_I("MobileGL closing...");
glslang::FinalizeProcess(); glslang::FinalizeProcess();
MG_Backend::pActiveBackendObject.reset();
MG_State::pGLContext.reset(); MG_State::pGLContext.reset();
MG_State::pEGLContext.reset(); MG_State::pEGLContext.reset();
MG_Impl::GLImpl::TextureImpl::pProxyTextureManager.reset(); MG_Impl::GLImpl::TextureImpl::pProxyTextureManager.reset();
MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo.reset(); MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo.reset();
MG_Backend::gBackendFunctionsTable = {};
g_isInitialized = false;
MG_Util::Debug::Close(); MG_Util::Debug::Close();
// TODO: add and use Destroy functions for other subsystems // TODO: add and use Destroy functions for other subsystems
+48
View File
@@ -112,6 +112,54 @@ namespace MobileGL {
struct DynamicBackendParameters { struct DynamicBackendParameters {
SizeT UniformBufferOffsetAlignment = 256; SizeT UniformBufferOffsetAlignment = 256;
Float AliasedLineWidthRangeMin = 1.0f;
Float AliasedLineWidthRangeMax = 1.0f;
Float SmoothLineWidthRangeMin = 1.0f;
Float SmoothLineWidthRangeMax = 1.0f;
Float SmoothLineWidthGranularity = 1.0f;
Float PointSizeRangeMin = 1.0f;
Float PointSizeRangeMax = 1.0f;
Float PointSizeGranularity = 1.0f;
Int Max3DTextureSize = 16384;
Int MaxArrayTextureLayers = 2048;
Int MaxCubeMapTextureSize = 16384;
Int MaxFramebufferWidth = 16384;
Int MaxFramebufferHeight = 16384;
Int MaxFramebufferLayers = 2048;
Int MaxRenderbufferSize = 16384;
Int MaxTextureSize = 16384;
Int MaxColorTextureSamples = 1;
Int MaxDepthTextureSamples = 1;
Int MaxFramebufferSamples = 1;
Int MaxIntegerSamples = 1;
Int MaxSamples = 1;
Int MaxSampleMaskWords = 1;
Int MaxTextureImageUnits = 32;
Int MaxVertexTextureImageUnits = 32;
Int MaxComputeTextureImageUnits = 32;
Int MaxCombinedTextureImageUnits = 192;
Int MaxVertexAttribs = 16;
Int MaxComputeShaderStorageBlocks = 8;
Int MaxCombinedShaderStorageBlocks = 32;
Int MaxComputeUniformBlocks = 12;
Int MaxComputeWorkGroupInvocations = 128;
Int MaxShaderStorageBufferBindings = 8;
Int MaxTextureBufferSize = 65536;
Int MaxUniformBufferBindings = 24;
Int MaxUniformBlockSize = 16384;
Int MaxImageUnits = 8;
Int MaxCombinedImageUniforms = 8;
Int MaxComputeImageUniforms = 8;
Int MaxDrawBuffers = 8;
Int MaxColorAttachments = 8;
Int MaxClipDistances = 8;
Int MaxViewports = 16;
Int MaxViewportWidth = 16384;
Int MaxViewportHeight = 16384;
Float ViewportBoundsRangeMin = 0.0f;
Float ViewportBoundsRangeMax = 0.0f;
Int ViewportSubpixelBits = 0;
Bool SupportsWideLines = false;
SizeT MaxShaderStorageBlockSize = 128 * 1024 * 1024; SizeT MaxShaderStorageBlockSize = 128 * 1024 * 1024;
Uint32 SubgroupSize = 0; Uint32 SubgroupSize = 0;
Uint32 SubgroupSupportedStages = 0; Uint32 SubgroupSupportedStages = 0;
@@ -34,18 +34,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
void BackendObject_DirectGLES::Initialize() { void BackendObject_DirectGLES::Initialize() {
if (!MG_Util::BackendLoader::AcquireEGLFunctions(m_EGLFunctions)) { MG_Util::BackendLoader::AcquireEGLFunctions(m_EGLFunctions);
MGLOG_E("Failed to acquire EGL functions for DirectGLES backend"); MG_Util::BackendLoader::AcquireGLESFunctions(m_GLESFunctions, m_EGLFunctions.eglGetProcAddress);
return;
}
if (!MG_Util::BackendLoader::AcquireGLESFunctions(m_GLESFunctions, m_EGLFunctions.eglGetProcAddress)) {
MGLOG_E("Failed to acquire GLES functions for DirectGLES backend");
return;
}
m_initialized = true;
DirectGLES::SetEGLFuncsTable(m_EGLFunctions); DirectGLES::SetEGLFuncsTable(m_EGLFunctions);
DirectGLES::SetGLESFuncsTable(m_GLESFunctions); DirectGLES::SetGLESFuncsTable(m_GLESFunctions);
m_initialized = true;
} }
Bool BackendObject_DirectGLES::InitCapabilities() { Bool BackendObject_DirectGLES::InitCapabilities() {
@@ -97,6 +90,21 @@ namespace MobileGL::MG_Backend::DirectGLES {
return BackendObject::CreateEGLWindowSurface(handle); return BackendObject::CreateEGLWindowSurface(handle);
} }
Bool BackendObject_DirectGLES::CreateEGLPbufferSurface(EGLint width, EGLint height) {
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
if (!m_initialized) {
MGLOG_E("DirectGLES backend not initialized");
return false;
}
if (m_eglSurfaceInitialized) {
DestroyEGLContext();
ResetEGLRuntimeState();
}
return BackendObject::CreateEGLPbufferSurface(width, height);
}
Bool BackendObject_DirectGLES::InitPbufferSurface(EGLint width, EGLint height) { Bool BackendObject_DirectGLES::InitPbufferSurface(EGLint width, EGLint height) {
return DirectGLES::InitPbufferSurface(width, height); return DirectGLES::InitPbufferSurface(width, height);
} }
@@ -221,6 +229,55 @@ namespace MobileGL::MG_Backend::DirectGLES {
void BackendObject_DirectGLES::UpdateDynamicBackendParameters() { void BackendObject_DirectGLES::UpdateDynamicBackendParameters() {
m_dynamicParameters.UniformBufferOffsetAlignment = m_GLESCapabilities.UniformBufferOffsetAlignment; m_dynamicParameters.UniformBufferOffsetAlignment = m_GLESCapabilities.UniformBufferOffsetAlignment;
m_dynamicParameters.AliasedLineWidthRangeMin = m_GLESCapabilities.AliasedLineWidthRangeMin;
m_dynamicParameters.AliasedLineWidthRangeMax = m_GLESCapabilities.AliasedLineWidthRangeMax;
m_dynamicParameters.SmoothLineWidthRangeMin = m_GLESCapabilities.SmoothLineWidthRangeMin;
m_dynamicParameters.SmoothLineWidthRangeMax = m_GLESCapabilities.SmoothLineWidthRangeMax;
m_dynamicParameters.SmoothLineWidthGranularity = m_GLESCapabilities.SmoothLineWidthGranularity;
m_dynamicParameters.PointSizeRangeMin = m_GLESCapabilities.PointSizeRangeMin;
m_dynamicParameters.PointSizeRangeMax = m_GLESCapabilities.PointSizeRangeMax;
m_dynamicParameters.PointSizeGranularity = m_GLESCapabilities.PointSizeGranularity;
m_dynamicParameters.Max3DTextureSize = m_GLESCapabilities.Max3DTextureSize;
m_dynamicParameters.MaxArrayTextureLayers = m_GLESCapabilities.MaxArrayTextureLayers;
m_dynamicParameters.MaxCubeMapTextureSize = m_GLESCapabilities.MaxCubeMapTextureSize;
m_dynamicParameters.MaxFramebufferWidth = m_GLESCapabilities.MaxFramebufferWidth;
m_dynamicParameters.MaxFramebufferHeight = m_GLESCapabilities.MaxFramebufferHeight;
m_dynamicParameters.MaxFramebufferLayers = m_GLESCapabilities.MaxFramebufferLayers;
m_dynamicParameters.MaxRenderbufferSize = m_GLESCapabilities.MaxRenderbufferSize;
m_dynamicParameters.MaxTextureSize = m_GLESCapabilities.MaxTextureSize;
m_dynamicParameters.MaxColorTextureSamples = m_GLESCapabilities.MaxColorTextureSamples;
m_dynamicParameters.MaxDepthTextureSamples = m_GLESCapabilities.MaxDepthTextureSamples;
m_dynamicParameters.MaxFramebufferSamples = m_GLESCapabilities.MaxFramebufferSamples;
m_dynamicParameters.MaxIntegerSamples = m_GLESCapabilities.MaxIntegerSamples;
m_dynamicParameters.MaxSamples = m_GLESCapabilities.MaxSamples;
m_dynamicParameters.MaxSampleMaskWords = m_GLESCapabilities.MaxSampleMaskWords;
m_dynamicParameters.MaxTextureImageUnits = m_GLESCapabilities.MaxTextureImageUnits;
m_dynamicParameters.MaxVertexTextureImageUnits = m_GLESCapabilities.MaxVertexTextureImageUnits;
m_dynamicParameters.MaxComputeTextureImageUnits = m_GLESCapabilities.MaxComputeTextureImageUnits;
m_dynamicParameters.MaxCombinedTextureImageUnits = m_GLESCapabilities.MaxCombinedTextureImageUnits;
m_dynamicParameters.MaxVertexAttribs = m_GLESCapabilities.MaxVertexAttribs;
m_dynamicParameters.MaxComputeShaderStorageBlocks = m_GLESCapabilities.MaxComputeShaderStorageBlocks;
m_dynamicParameters.MaxCombinedShaderStorageBlocks = m_GLESCapabilities.MaxCombinedShaderStorageBlocks;
m_dynamicParameters.MaxComputeUniformBlocks = m_GLESCapabilities.MaxComputeUniformBlocks;
m_dynamicParameters.MaxComputeWorkGroupInvocations = m_GLESCapabilities.MaxComputeWorkGroupInvocations;
m_dynamicParameters.MaxShaderStorageBufferBindings = m_GLESCapabilities.MaxShaderStorageBufferBindings;
m_dynamicParameters.MaxTextureBufferSize = m_GLESCapabilities.MaxTextureBufferSize;
m_dynamicParameters.MaxUniformBufferBindings = m_GLESCapabilities.MaxUniformBufferBindings;
m_dynamicParameters.MaxUniformBlockSize = m_GLESCapabilities.MaxUniformBlockSize;
m_dynamicParameters.MaxImageUnits = m_GLESCapabilities.MaxImageUnits;
m_dynamicParameters.MaxCombinedImageUniforms = m_GLESCapabilities.MaxCombinedImageUniforms;
m_dynamicParameters.MaxComputeImageUniforms = m_GLESCapabilities.MaxComputeImageUniforms;
m_dynamicParameters.MaxDrawBuffers = m_GLESCapabilities.MaxDrawBuffers;
m_dynamicParameters.MaxColorAttachments = m_GLESCapabilities.MaxColorAttachments;
m_dynamicParameters.MaxClipDistances = m_GLESCapabilities.MaxClipDistances;
m_dynamicParameters.MaxViewports = m_GLESCapabilities.MaxViewports;
m_dynamicParameters.MaxViewportWidth = m_GLESCapabilities.MaxViewportWidth;
m_dynamicParameters.MaxViewportHeight = m_GLESCapabilities.MaxViewportHeight;
m_dynamicParameters.ViewportBoundsRangeMin = m_GLESCapabilities.ViewportBoundsRangeMin;
m_dynamicParameters.ViewportBoundsRangeMax = m_GLESCapabilities.ViewportBoundsRangeMax;
m_dynamicParameters.ViewportSubpixelBits = m_GLESCapabilities.ViewportSubpixelBits;
m_dynamicParameters.SupportsWideLines =
m_GLESCapabilities.AliasedLineWidthRangeMax > 1.0f || m_GLESCapabilities.SmoothLineWidthRangeMax > 1.0f;
} }
const MG_External::GLESFunctionsTable& BackendObject_DirectGLES::GetGLESFunctions() const { const MG_External::GLESFunctionsTable& BackendObject_DirectGLES::GetGLESFunctions() const {
@@ -21,6 +21,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
Bool InitWindowSurface() override; Bool InitWindowSurface() override;
Bool InitializeEGLDisplay(EGLDisplay dpy, EGLint* major, EGLint* minor) override; Bool InitializeEGLDisplay(EGLDisplay dpy, EGLint* major, EGLint* minor) override;
Bool CreateEGLWindowSurface(const WindowHandle& handle) override; Bool CreateEGLWindowSurface(const WindowHandle& handle) override;
Bool CreateEGLPbufferSurface(EGLint width, EGLint height) override;
Bool MakeEGLCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) override; Bool MakeEGLCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) override;
Bool SwapEGLBuffers(EGLDisplay dpy, EGLSurface draw) override; Bool SwapEGLBuffers(EGLDisplay dpy, EGLSurface draw) override;
void ReleaseEGLResources() override; void ReleaseEGLResources() override;
+206 -28
View File
@@ -65,6 +65,34 @@ namespace MobileGL::MG_Backend::DirectGLES {
Uint32 baseInstance = 0; Uint32 baseInstance = 0;
}; };
struct DrawArraysIndirectCommand {
Uint32 count = 0;
Uint32 instanceCount = 0;
Uint32 first = 0;
Uint32 baseInstance = 0;
};
const Uint8* ResolveIndirectCommandBytes(const void* indirect, SizeT requiredBytes, const char* label) {
auto drawBuffer = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
if (drawBuffer) {
drawBuffer->MarkPersistentMappedRangeDirty();
const auto drawData = drawBuffer->GetDataReadOnly();
const SizeT commandOffset = reinterpret_cast<SizeT>(indirect);
if (!drawData || commandOffset + requiredBytes > drawData->size()) {
MGLOG_E("%s skipped: invalid GL_DRAW_INDIRECT_BUFFER binding or range", label);
return nullptr;
}
return drawData->data() + commandOffset;
}
if (!indirect) {
MGLOG_E("%s skipped: indirect pointer is null", label);
return nullptr;
}
return reinterpret_cast<const Uint8*>(indirect);
}
namespace DebugImpl { namespace DebugImpl {
#if MOBILEGL_LOG_ACTIVE_LEVEL <= MOBILEGL_LOG_LEVEL_DEBUG #if MOBILEGL_LOG_ACTIVE_LEVEL <= MOBILEGL_LOG_LEVEL_DEBUG
void ErrorLopper::Loop(const std::function<void(GLenum)>& func) { void ErrorLopper::Loop(const std::function<void(GLenum)>& func) {
@@ -425,7 +453,16 @@ namespace MobileGL::MG_Backend::DirectGLES {
} \ } \
} }
SYNC_CAPABILITY(DepthTest, GL_DEPTH_TEST); SYNC_CAPABILITY(DepthTest, GL_DEPTH_TEST);
SYNC_CAPABILITY(ColorLogicOp, GL_COLOR_LOGIC_OP);
SYNC_CAPABILITY(Dither, GL_DITHER);
SYNC_CAPABILITY(Multisample, GL_MULTISAMPLE);
SYNC_CAPABILITY(SampleAlphaToCoverage, GL_SAMPLE_ALPHA_TO_COVERAGE);
SYNC_CAPABILITY(SampleCoverage, GL_SAMPLE_COVERAGE);
SYNC_CAPABILITY(SampleMask, GL_SAMPLE_MASK);
SYNC_CAPABILITY(PolygonOffsetFill, GL_POLYGON_OFFSET_FILL);
SYNC_CAPABILITY(RasterizerDiscard, GL_RASTERIZER_DISCARD);
SYNC_CAPABILITY(ScissorTest, GL_SCISSOR_TEST); SYNC_CAPABILITY(ScissorTest, GL_SCISSOR_TEST);
SYNC_CAPABILITY(StencilTest, GL_STENCIL_TEST);
SYNC_CAPABILITY(CullFace, GL_CULL_FACE); SYNC_CAPABILITY(CullFace, GL_CULL_FACE);
#undef SYNC_CAPABILITY #undef SYNC_CAPABILITY
@@ -538,6 +575,34 @@ namespace MobileGL::MG_Backend::DirectGLES {
if (parameters.DepthMask != g_syncedRenderStateParameters.DepthMask) { if (parameters.DepthMask != g_syncedRenderStateParameters.DepthMask) {
g_GLESFuncs.glDepthMask(parameters.DepthMask ? GL_TRUE : GL_FALSE); g_GLESFuncs.glDepthMask(parameters.DepthMask ? GL_TRUE : GL_FALSE);
} }
if (parameters.DepthRange != g_syncedRenderStateParameters.DepthRange) {
g_GLESFuncs.glDepthRangef(parameters.DepthRange.x(), parameters.DepthRange.y());
}
}
{ // Stencil state
for (SizeT faceIndex = 0; faceIndex < parameters.StencilStates.size(); ++faceIndex) {
const StencilFaceState& current = parameters.StencilStates[faceIndex];
const StencilFaceState& synced = g_syncedRenderStateParameters.StencilStates[faceIndex];
const GLenum glFace = faceIndex == 0 ? GL_FRONT : GL_BACK;
if (current.Func != synced.Func || current.Ref != synced.Ref ||
current.ValueMask != synced.ValueMask) {
g_GLESFuncs.glStencilFuncSeparate(
glFace, MG_Util::ConvertDepthTestFuncToGLEnum(current.Func), current.Ref,
current.ValueMask);
}
if (current.WriteMask != synced.WriteMask) {
g_GLESFuncs.glStencilMaskSeparate(glFace, current.WriteMask);
}
if (current.FailOp != synced.FailOp || current.PassDepthFailOp != synced.PassDepthFailOp ||
current.PassDepthPassOp != synced.PassDepthPassOp) {
g_GLESFuncs.glStencilOpSeparate(
glFace, MG_Util::ConvertStencilOperationToGLEnum(current.FailOp),
MG_Util::ConvertStencilOperationToGLEnum(current.PassDepthFailOp),
MG_Util::ConvertStencilOperationToGLEnum(current.PassDepthPassOp));
}
}
} }
{ // Color mask { // Color mask
@@ -556,6 +621,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
if (parameters.ClearDepth != g_syncedRenderStateParameters.ClearDepth) { if (parameters.ClearDepth != g_syncedRenderStateParameters.ClearDepth) {
g_GLESFuncs.glClearDepthf(parameters.ClearDepth); g_GLESFuncs.glClearDepthf(parameters.ClearDepth);
} }
if (parameters.BlendColor != g_syncedRenderStateParameters.BlendColor) {
const FloatVec4& blendColor = parameters.BlendColor;
g_GLESFuncs.glBlendColor(blendColor.x(), blendColor.y(), blendColor.z(), blendColor.w());
}
} }
{ // Cull face mode { // Cull face mode
@@ -576,6 +645,45 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
} }
{ // Logic op
if (parameters.LogicOp != g_syncedRenderStateParameters.LogicOp) {
g_GLESFuncs.glLogicOp(MG_Util::ConvertLogicOperationToGLEnum(parameters.LogicOp));
}
}
{ // Polygon offset
if (parameters.PolygonOffsetFactor != g_syncedRenderStateParameters.PolygonOffsetFactor ||
parameters.PolygonOffsetUnits != g_syncedRenderStateParameters.PolygonOffsetUnits) {
g_GLESFuncs.glPolygonOffset(parameters.PolygonOffsetFactor, parameters.PolygonOffsetUnits);
}
}
{ // Line width
if (parameters.LineWidth != g_syncedRenderStateParameters.LineWidth) {
g_GLESFuncs.glLineWidth(parameters.LineWidth);
}
}
{ // Point size
if (parameters.PointSize != g_syncedRenderStateParameters.PointSize) {
g_GLESFuncs.glPointSize(parameters.PointSize);
}
}
{ // Sample coverage
if (parameters.SampleCoverageValue != g_syncedRenderStateParameters.SampleCoverageValue ||
parameters.SampleCoverageInvert != g_syncedRenderStateParameters.SampleCoverageInvert) {
g_GLESFuncs.glSampleCoverage(parameters.SampleCoverageValue,
ToGLBoolean(parameters.SampleCoverageInvert));
}
}
{ // Sample mask
if (g_GLESFuncs.glSampleMaski && parameters.SampleMaskValue != g_syncedRenderStateParameters.SampleMaskValue) {
g_GLESFuncs.glSampleMaski(0, parameters.SampleMaskValue);
}
}
g_syncedRenderStateVersion = currentRenderStateVersion; g_syncedRenderStateVersion = currentRenderStateVersion;
g_syncedRenderStateParameters = parameters; g_syncedRenderStateParameters = parameters;
g_hasSyncedRenderState = true; g_hasSyncedRenderState = true;
@@ -1006,24 +1114,17 @@ namespace MobileGL::MG_Backend::DirectGLES {
return; return;
} }
auto drawBuffer = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject(); const auto* commandBytes = ResolveIndirectCommandBytes(
if (!drawBuffer) { indirect,
MGLOG_E("MultiDrawElementsIndirect skipped: no GL_DRAW_INDIRECT_BUFFER is bound"); static_cast<SizeT>(stride) * static_cast<SizeT>(drawcount - 1) + sizeof(DrawElementsIndirectCommand),
return; "MultiDrawElementsIndirect");
} if (!commandBytes) {
drawBuffer->MarkPersistentMappedRangeDirty();
const auto drawData = drawBuffer->GetDataReadOnly();
const SizeT commandOffset = reinterpret_cast<SizeT>(indirect);
const SizeT commandBytes = commandOffset + static_cast<SizeT>(stride) * static_cast<SizeT>(drawcount - 1) +
sizeof(DrawElementsIndirectCommand);
if (!drawData || commandBytes > drawData->size()) {
MGLOG_E("MultiDrawElementsIndirect skipped: invalid GL_DRAW_INDIRECT_BUFFER binding or range");
return; return;
} }
for (GLsizei i = 0; i < drawcount; ++i) { for (GLsizei i = 0; i < drawcount; ++i) {
DrawElementsIndirectCommand cmd{}; DrawElementsIndirectCommand cmd{};
std::memcpy(&cmd, drawData->data() + commandOffset + static_cast<SizeT>(i) * stride, sizeof(cmd)); std::memcpy(&cmd, commandBytes + static_cast<SizeT>(i) * stride, sizeof(cmd));
if (cmd.count == 0 || cmd.instanceCount == 0) { if (cmd.count == 0 || cmd.instanceCount == 0) {
continue; continue;
} }
@@ -1112,14 +1213,41 @@ namespace MobileGL::MG_Backend::DirectGLES {
#if MOBILEGL_LOG_ACTIVE_LEVEL <= MOBILEGL_LOG_LEVEL_DEBUG && MOBILEGL_ENABLE_SCOPE_MARKER #if MOBILEGL_LOG_ACTIVE_LEVEL <= MOBILEGL_LOG_LEVEL_DEBUG && MOBILEGL_ENABLE_SCOPE_MARKER
DebugImpl::OpenGLScopeMarker marker(__func__); DebugImpl::OpenGLScopeMarker marker(__func__);
#endif #endif
DrawSyncBit syncBit = DrawSyncBit::IndirectBuffer; if (drawcount <= 0) {
return;
}
if (stride == 0) {
stride = sizeof(DrawArraysIndirectCommand);
}
if (stride < static_cast<GLsizei>(sizeof(DrawArraysIndirectCommand))) {
MGLOG_E("MultiDrawArraysIndirect skipped: stride %d is smaller than command size %zu",
stride, sizeof(DrawArraysIndirectCommand));
return;
}
DrawSyncBit syncBit = DrawSyncBit::IndirectBuffer | DrawSyncBit::Instancing;
PrepareForDraw(syncBit); PrepareForDraw(syncBit);
for (GLsizei i = 0; i < drawcount; ++i) { const auto* commandBytes = ResolveIndirectCommandBytes(
const GLvoid* cmd = reinterpret_cast<const GLvoid*>(reinterpret_cast<const uint8_t*>(indirect) + indirect,
i * (stride ? stride : sizeof(GLsizei) * 4)); static_cast<SizeT>(stride) * static_cast<SizeT>(drawcount - 1) + sizeof(DrawArraysIndirectCommand),
g_GLESFuncs.glDrawArraysIndirect(mode, cmd); "MultiDrawArraysIndirect");
if (!commandBytes) {
return;
} }
for (GLsizei i = 0; i < drawcount; ++i) {
DrawArraysIndirectCommand cmd{};
std::memcpy(&cmd, commandBytes + static_cast<SizeT>(i) * stride, sizeof(cmd));
if (cmd.count == 0 || cmd.instanceCount == 0) {
continue;
}
SetCurrentBaseInstance(cmd.baseInstance);
g_GLESFuncs.glDrawArraysInstanced(
mode, static_cast<GLint>(cmd.first), static_cast<GLsizei>(cmd.count),
static_cast<GLsizei>(cmd.instanceCount));
}
SetCurrentBaseInstance(0);
} }
void DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, void DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type,
@@ -1137,8 +1265,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
void DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices, void DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices,
GLsizei instancecount, GLint basevertex, GLuint baseinstance) { GLsizei instancecount, GLint basevertex, GLuint baseinstance) {
// Not supported in OpenGL ES DrawSyncBit syncBit = DrawSyncBit::IndexBuffer | DrawSyncBit::Instancing;
MGLOG_W("DrawElementsInstancedBaseVertexBaseInstance is not supported in OpenGL ES."); PrepareForDraw(syncBit);
SetCurrentBaseInstance(baseinstance);
g_GLESFuncs.glDrawElementsInstancedBaseVertex(mode, count, type, indices, instancecount, basevertex);
SetCurrentBaseInstance(0);
} }
void DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type, const void* indices, void DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type, const void* indices,
@@ -1150,8 +1281,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
void DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices, void DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices,
GLsizei instancecount, GLuint baseinstance) { GLsizei instancecount, GLuint baseinstance) {
// Not supported in OpenGL ES DrawSyncBit syncBit = DrawSyncBit::IndexBuffer | DrawSyncBit::Instancing;
MGLOG_W("DrawElementsInstancedBaseInstance is not supported in OpenGL ES."); PrepareForDraw(syncBit);
SetCurrentBaseInstance(baseinstance);
g_GLESFuncs.glDrawElementsInstanced(mode, count, type, indices, instancecount);
SetCurrentBaseInstance(0);
} }
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) {
@@ -1161,15 +1295,42 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
void DrawElementsIndirect(GLenum mode, GLenum type, const void* indirect) { void DrawElementsIndirect(GLenum mode, GLenum type, const void* indirect) {
DrawSyncBit syncBit = DrawSyncBit::IndexBuffer | DrawSyncBit::IndirectBuffer; DrawSyncBit syncBit = DrawSyncBit::IndexBuffer | DrawSyncBit::IndirectBuffer | DrawSyncBit::Instancing;
PrepareForDraw(syncBit); PrepareForDraw(syncBit);
g_GLESFuncs.glDrawElementsIndirect(mode, type, indirect);
const SizeT indexSize = MG_Util::GetGLTypeSize(type);
if (indexSize == 0) {
MGLOG_E("DrawElementsIndirect skipped: unsupported index type 0x%x", type);
return;
}
const auto* commandBytes =
ResolveIndirectCommandBytes(indirect, sizeof(DrawElementsIndirectCommand), "DrawElementsIndirect");
if (!commandBytes) {
return;
}
DrawElementsIndirectCommand cmd{};
std::memcpy(&cmd, commandBytes, sizeof(cmd));
if (cmd.count == 0 || cmd.instanceCount == 0) {
return;
}
SetCurrentBaseInstance(cmd.baseInstance);
const auto indexByteOffset = static_cast<SizeT>(cmd.firstIndex) * indexSize;
g_GLESFuncs.glDrawElementsInstancedBaseVertex(
mode, static_cast<GLsizei>(cmd.count), type, reinterpret_cast<const GLvoid*>(indexByteOffset),
static_cast<GLsizei>(cmd.instanceCount), cmd.baseVertex);
SetCurrentBaseInstance(0);
} }
void DrawArraysInstancedBaseInstance(GLenum mode, GLint first, GLsizei count, GLsizei instancecount, void DrawArraysInstancedBaseInstance(GLenum mode, GLint first, GLsizei count, GLsizei instancecount,
GLuint baseinstance) { GLuint baseinstance) {
// Not supported in OpenGL ES DrawSyncBit syncBit = DrawSyncBit::Instancing;
MGLOG_W("DrawArraysInstancedBaseInstance is not supported in OpenGL ES."); PrepareForDraw(syncBit);
SetCurrentBaseInstance(baseinstance);
g_GLESFuncs.glDrawArraysInstanced(mode, first, count, instancecount);
SetCurrentBaseInstance(0);
} }
void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount) { void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount) {
@@ -1179,9 +1340,26 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
void DrawArraysIndirect(GLenum mode, const void* indirect) { void DrawArraysIndirect(GLenum mode, const void* indirect) {
DrawSyncBit syncBit = DrawSyncBit::IndirectBuffer; DrawSyncBit syncBit = DrawSyncBit::IndirectBuffer | DrawSyncBit::Instancing;
PrepareForDraw(syncBit); PrepareForDraw(syncBit);
g_GLESFuncs.glDrawArraysIndirect(mode, indirect);
const auto* commandBytes =
ResolveIndirectCommandBytes(indirect, sizeof(DrawArraysIndirectCommand), "DrawArraysIndirect");
if (!commandBytes) {
return;
}
DrawArraysIndirectCommand cmd{};
std::memcpy(&cmd, commandBytes, sizeof(cmd));
if (cmd.count == 0 || cmd.instanceCount == 0) {
return;
}
SetCurrentBaseInstance(cmd.baseInstance);
g_GLESFuncs.glDrawArraysInstanced(
mode, static_cast<GLint>(cmd.first), static_cast<GLsizei>(cmd.count),
static_cast<GLsizei>(cmd.instanceCount));
SetCurrentBaseInstance(0);
} }
void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1,
+89 -5
View File
@@ -541,7 +541,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
static_cast<SizeT>(baseSize.y()), static_cast<SizeT>(baseSize.y()),
static_cast<SizeT>(baseSize.z()), static_cast<SizeT>(baseSize.z()),
0, 0,
0}; 0,
stateTextureObject->GetSamples(),
stateTextureObject->HasFixedSampleLocations()};
switch (stateTextureObject->GetStorageType()) { switch (stateTextureObject->GetStorageType()) {
case TextureStorageType::Mipmap: { case TextureStorageType::Mipmap: {
auto* textureMipmapObject = auto* textureMipmapObject =
@@ -565,6 +567,33 @@ namespace MobileGL::MG_Backend::DirectGLES {
&glFormat, &glType); &glFormat, &glType);
const auto& uploadTargets = textureMipmapObject->GetUploadTargets(); const auto& uploadTargets = textureMipmapObject->GetUploadTargets();
if (TextureImpl::IsMultisampleTextureTarget(targetInternal)) {
DebugImpl::ErrorLopper::Clear();
g_GLESFuncs.glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
switch (targetInternal) {
case TextureTarget::Texture2DMultisample:
g_GLESFuncs.glTexStorage2DMultisample(
target, static_cast<GLsizei>(stateTextureObject->GetSamples()), glInternalFormat,
static_cast<GLsizei>(baseSize.x()), static_cast<GLsizei>(baseSize.y()),
stateTextureObject->HasFixedSampleLocations() ? GL_TRUE : GL_FALSE);
break;
case TextureTarget::Texture2DMultisampleArray:
g_GLESFuncs.glTexStorage3DMultisample(
target, static_cast<GLsizei>(stateTextureObject->GetSamples()), glInternalFormat,
static_cast<GLsizei>(baseSize.x()), static_cast<GLsizei>(baseSize.y()),
static_cast<GLsizei>(baseSize.z()),
stateTextureObject->HasFixedSampleLocations() ? GL_TRUE : GL_FALSE);
break;
default:
MOBILEGL_ASSERT(false, "Unexpected multisample target: %d", static_cast<Int>(targetInternal));
break;
}
for (const auto& uploadTarget : uploadTargets) {
for (SizeT level = 0; level < mipmapCount; ++level) {
textureMipmapObject->MarkStorageDirty(uploadTarget, level, false);
}
}
} else {
for (auto& uploadTarget : uploadTargets) { for (auto& uploadTarget : uploadTargets) {
for (SizeT level = 0; level < mipmapCount; ++level) { for (SizeT level = 0; level < mipmapCount; ++level) {
auto levelTexelSize = textureMipmapObject->GetMipmapTexelSize(uploadTarget, level); auto levelTexelSize = textureMipmapObject->GetMipmapTexelSize(uploadTarget, level);
@@ -620,11 +649,24 @@ namespace MobileGL::MG_Backend::DirectGLES {
textureMipmapObject->MarkStorageDirty(uploadTarget, level, false); textureMipmapObject->MarkStorageDirty(uploadTarget, level, false);
} }
} }
}
m_isInitialized = true; m_isInitialized = true;
} }
{ // Update all dirty mipmap levels { // Update all dirty mipmap levels
if (TextureImpl::IsMultisampleTextureTarget(targetInternal)) {
const auto& uploadTargets = textureMipmapObject->GetUploadTargets();
for (const auto& uploadTarget : uploadTargets) {
for (SizeT level = 0; level < mipmapCount; ++level) {
if (textureMipmapObject->IsStorageDirty(uploadTarget, level)) {
textureMipmapObject->MarkStorageDirty(uploadTarget, level, false);
}
}
}
break;
}
const auto mipmapCount = textureMipmapObject->GetMipmapLevelCount(); const auto mipmapCount = textureMipmapObject->GetMipmapLevelCount();
GLenum glInternalFormat, glType, glFormat; GLenum glInternalFormat, glType, glFormat;
TextureImpl::GenerateTextureFormatInfo(textureMipmapObject->GetFormat(), &glInternalFormat, TextureImpl::GenerateTextureFormatInfo(textureMipmapObject->GetFormat(), &glInternalFormat,
@@ -657,10 +699,27 @@ namespace MobileGL::MG_Backend::DirectGLES {
MG_Util::ConvertGLEnumToString(err).c_str()); MG_Util::ConvertGLEnumToString(err).c_str());
}); });
auto texelSize = textureMipmapObject->GetMipmapTexelSize(uploadTarget, level); auto texelSize = textureMipmapObject->GetMipmapTexelSize(uploadTarget, level);
const void* mipData = textureMipmapObject->MapMipmapData(uploadTarget, level);
switch (stateTextureObject->GetTarget()) {
case TextureTarget::Texture2D:
case TextureTarget::TextureCubeMap:
g_GLESFuncs.glTexSubImage2D(glUploadTarget, static_cast<GLint>(level), 0, 0, g_GLESFuncs.glTexSubImage2D(glUploadTarget, static_cast<GLint>(level), 0, 0,
static_cast<GLsizei>(texelSize.x()), static_cast<GLsizei>(texelSize.x()),
static_cast<GLsizei>(texelSize.y()), glFormat, glType, static_cast<GLsizei>(texelSize.y()), glFormat, glType,
textureMipmapObject->MapMipmapData(uploadTarget, level)); mipData);
break;
case TextureTarget::Texture3D:
g_GLESFuncs.glTexSubImage3D(glUploadTarget, static_cast<GLint>(level), 0, 0, 0,
static_cast<GLsizei>(texelSize.x()),
static_cast<GLsizei>(texelSize.y()),
static_cast<GLsizei>(texelSize.z()), glFormat, glType,
mipData);
break;
default:
MGLOG_E("Unhandled texture target %s",
MG_Util::ConvertTextureTargetToString(stateTextureObject->GetTarget()).c_str());
break;
}
textureMipmapObject->MarkStorageDirty(uploadTarget, level, false); textureMipmapObject->MarkStorageDirty(uploadTarget, level, false);
} }
} }
@@ -763,6 +822,12 @@ namespace MobileGL::MG_Backend::DirectGLES {
return; return;
} }
const auto& samplerParams = samplerObject->GetAllSamplerParameters();
if (TextureImpl::IsMultisampleTextureTarget(targetInternal)) {
m_cacheSamplerParameters = samplerParams;
return;
}
Bind(target); Bind(target);
DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) {
MGLOG_D("%s(%s:%d) ES error: %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("%s(%s:%d) ES error: %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str());
@@ -770,7 +835,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
// Update built-in sampler parameters // Update built-in sampler parameters
MGLOG_D("Updating sampler parameters for texture with ID: %u", m_backendTextureId); MGLOG_D("Updating sampler parameters for texture with ID: %u", m_backendTextureId);
const auto& samplerParams = samplerObject->GetAllSamplerParameters();
#define SYNC_TEX_SAMPLER_PARAM_IF_CHANGED(internalName, glName, type) \ #define SYNC_TEX_SAMPLER_PARAM_IF_CHANGED(internalName, glName, type) \
if (m_cacheSamplerParameters.internalName != samplerParams.internalName) { \ if (m_cacheSamplerParameters.internalName != samplerParams.internalName) { \
@@ -857,6 +921,13 @@ namespace MobileGL::MG_Backend::DirectGLES {
return; return;
} }
if (TextureImpl::IsMultisampleTextureTarget(targetInternal)) {
m_cacheLodRange = stateTextureObject->GetLevelRange();
m_cacheSwizzleParams = stateTextureObject->GetAllSwizzleParams();
m_cacheBorderColor = stateTextureObject->GetBorderColor();
return;
}
Bind(target); Bind(target);
DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) {
MGLOG_D("%s(%s:%d) ES error: %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("%s(%s:%d) ES error: %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str());
@@ -993,7 +1064,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
return false; return false;
} }
backendTextureObject->SyncMipmapsToBackend(textureObject); backendTextureObject->SyncMipmapsToBackend(textureObject);
auto glTextureTarget = MG_Util::ConvertTextureTargetToGLEnum(textureObject->GetTarget()); auto glTextureTarget =
MG_Util::ConvertTextureUploadTargetToGLEnum(attachmentObject.GetTextureUploadTarget());
if (glTextureTarget == GL_UNKNOWN_MGL) {
glTextureTarget = MG_Util::ConvertTextureTargetToGLEnum(textureObject->GetTarget());
}
backendTextureObject->Bind(glTextureTarget); backendTextureObject->Bind(glTextureTarget);
g_GLESFuncs.glFramebufferTexture2D(glFBOTarget, glBackendAttachment, glTextureTarget, g_GLESFuncs.glFramebufferTexture2D(glFBOTarget, glBackendAttachment, glTextureTarget,
backendTextureObject->GetBackendTextureId(), backendTextureObject->GetBackendTextureId(),
@@ -1523,7 +1598,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
stateRBOObject->GetExternalIndex()); stateRBOObject->GetExternalIndex());
if (m_isInitialized && m_cacheInternalFormat == stateRBOObject->GetInternalFormat() && if (m_isInitialized && m_cacheInternalFormat == stateRBOObject->GetInternalFormat() &&
m_cacheWidth == stateRBOObject->GetWidth() && m_cacheHeight == stateRBOObject->GetHeight()) { m_cacheWidth == stateRBOObject->GetWidth() && m_cacheHeight == stateRBOObject->GetHeight() &&
m_cacheSamples == stateRBOObject->GetSamples()) {
MGLOG_D("RBO %u already initialized with matching parameters, skipping re-allocation.", MGLOG_D("RBO %u already initialized with matching parameters, skipping re-allocation.",
stateRBOObject->GetExternalIndex()); stateRBOObject->GetExternalIndex());
return; return;
@@ -1535,15 +1611,23 @@ namespace MobileGL::MG_Backend::DirectGLES {
TextureInternalFormat internalFormat = stateRBOObject->GetInternalFormat(); TextureInternalFormat internalFormat = stateRBOObject->GetInternalFormat();
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());
Int samples = static_cast<Int>(stateRBOObject->GetSamples());
GLenum glInternalFormat, glType, glFormat; GLenum glInternalFormat, glType, glFormat;
TextureImpl::GenerateTextureFormatInfo(internalFormat, &glInternalFormat, &glFormat, &glType); TextureImpl::GenerateTextureFormatInfo(internalFormat, &glInternalFormat, &glFormat, &glType);
if (samples > 0) {
g_GLESFuncs.glRenderbufferStorageMultisample(
GL_RENDERBUFFER, static_cast<GLsizei>(samples), glInternalFormat, static_cast<GLsizei>(width),
static_cast<GLsizei>(height));
} else {
g_GLESFuncs.glRenderbufferStorage(GL_RENDERBUFFER, glInternalFormat, static_cast<GLsizei>(width), g_GLESFuncs.glRenderbufferStorage(GL_RENDERBUFFER, glInternalFormat, static_cast<GLsizei>(width),
static_cast<GLsizei>(height)); static_cast<GLsizei>(height));
}
m_cacheInternalFormat = internalFormat; m_cacheInternalFormat = internalFormat;
m_cacheWidth = width; m_cacheWidth = width;
m_cacheHeight = height; m_cacheHeight = height;
m_cacheSamples = samples;
m_isInitialized = true; m_isInitialized = true;
MGLOG_D("RBO %u sync completed. backend ID %u", stateRBOObject->GetExternalIndex(), m_backendRBOId); MGLOG_D("RBO %u sync completed. backend ID %u", stateRBOObject->GetExternalIndex(), m_backendRBOId);
+11 -3
View File
@@ -162,12 +162,16 @@ namespace MobileGL::MG_Backend::DirectGLES {
namespace TextureImpl { namespace TextureImpl {
inline Bool IsSupportedTextureTarget(TextureTarget target) { inline Bool IsSupportedTextureTarget(TextureTarget target) {
if (target == TextureTarget::Texture1D || target == TextureTarget::TextureRectangle || if (target == TextureTarget::Texture1D || target == TextureTarget::TextureRectangle ||
target == TextureTarget::Texture2DMultisampleArray || target == TextureTarget::Texture1DArray || target == TextureTarget::Texture1DArray || target == TextureTarget::Texture2DArray)
target == TextureTarget::Texture2DMultisample || target == TextureTarget::Texture2DArray)
return false; return false;
return true; return true;
} }
inline Bool IsMultisampleTextureTarget(TextureTarget target) {
return target == TextureTarget::Texture2DMultisample ||
target == TextureTarget::Texture2DMultisampleArray;
}
inline Bool SupportsWrapR(TextureTarget target) { inline Bool SupportsWrapR(TextureTarget target) {
return target == TextureTarget::Texture3D || target == TextureTarget::TextureCubeMap; return target == TextureTarget::Texture3D || target == TextureTarget::TextureCubeMap;
} }
@@ -179,11 +183,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
SizeT depth = 0; SizeT depth = 0;
SizeT mipmapLevels = 0; SizeT mipmapLevels = 0;
Uint bufferExternalIndex = 0; Uint bufferExternalIndex = 0;
Int samples = 0;
Bool fixedSampleLocations = true;
bool operator==(const StateTextureBasicInfo& other) const { bool operator==(const StateTextureBasicInfo& other) const {
return internalFormat == other.internalFormat && width == other.width && height == other.height && return internalFormat == other.internalFormat && width == other.width && height == other.height &&
depth == other.depth && mipmapLevels == other.mipmapLevels && depth == other.depth && mipmapLevels == other.mipmapLevels &&
bufferExternalIndex == other.bufferExternalIndex; bufferExternalIndex == other.bufferExternalIndex && samples == other.samples &&
fixedSampleLocations == other.fixedSampleLocations;
} }
bool operator!=(const StateTextureBasicInfo& other) const { return !(*this == other); } bool operator!=(const StateTextureBasicInfo& other) const { return !(*this == other); }
@@ -322,6 +329,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
TextureInternalFormat m_cacheInternalFormat = TextureInternalFormat::Unknown; TextureInternalFormat m_cacheInternalFormat = TextureInternalFormat::Unknown;
Int m_cacheWidth = 0; Int m_cacheWidth = 0;
Int m_cacheHeight = 0; Int m_cacheHeight = 0;
Int m_cacheSamples = 0;
}; };
extern StateBackendObjectRegistry<MG_State::GLState::RenderbufferObject, BackendRenderbufferObject> extern StateBackendObjectRegistry<MG_State::GLState::RenderbufferObject, BackendRenderbufferObject>
+1 -1
View File
@@ -149,7 +149,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
while (GLenum err = g_GLESFuncs.glGetError() != GL_NO_ERROR) { for (GLenum err = g_GLESFuncs.glGetError(); err != GL_NO_ERROR; err = g_GLESFuncs.glGetError()) {
MGLOG_E("-> GLES Error: %s", MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_E("-> GLES Error: %s", MG_Util::ConvertGLEnumToString(err).c_str());
} }
} }
@@ -283,6 +283,54 @@ namespace MobileGL::MG_Backend::DirectVulkan {
static constexpr SizeT kMaxAdvertisedShaderStorageBlockSize = 512ull * 1024ull * 1024ull; static constexpr SizeT kMaxAdvertisedShaderStorageBlockSize = 512ull * 1024ull * 1024ull;
m_dynamicParameters.UniformBufferOffsetAlignment = m_vulkanCaps.UniformBufferOffsetAlignment; m_dynamicParameters.UniformBufferOffsetAlignment = m_vulkanCaps.UniformBufferOffsetAlignment;
m_dynamicParameters.AliasedLineWidthRangeMin = m_vulkanCaps.AliasedLineWidthRangeMin;
m_dynamicParameters.AliasedLineWidthRangeMax = m_vulkanCaps.AliasedLineWidthRangeMax;
m_dynamicParameters.SmoothLineWidthRangeMin = m_vulkanCaps.SmoothLineWidthRangeMin;
m_dynamicParameters.SmoothLineWidthRangeMax = m_vulkanCaps.SmoothLineWidthRangeMax;
m_dynamicParameters.SmoothLineWidthGranularity = m_vulkanCaps.SmoothLineWidthGranularity;
m_dynamicParameters.PointSizeRangeMin = m_vulkanCaps.PointSizeRangeMin;
m_dynamicParameters.PointSizeRangeMax = m_vulkanCaps.PointSizeRangeMax;
m_dynamicParameters.PointSizeGranularity = m_vulkanCaps.PointSizeGranularity;
m_dynamicParameters.Max3DTextureSize = m_vulkanCaps.Max3DTextureSize;
m_dynamicParameters.MaxArrayTextureLayers = m_vulkanCaps.MaxArrayTextureLayers;
m_dynamicParameters.MaxCubeMapTextureSize = m_vulkanCaps.MaxCubeMapTextureSize;
m_dynamicParameters.MaxFramebufferWidth = m_vulkanCaps.MaxFramebufferWidth;
m_dynamicParameters.MaxFramebufferHeight = m_vulkanCaps.MaxFramebufferHeight;
m_dynamicParameters.MaxFramebufferLayers = m_vulkanCaps.MaxFramebufferLayers;
m_dynamicParameters.MaxRenderbufferSize = m_vulkanCaps.MaxRenderbufferSize;
m_dynamicParameters.MaxTextureSize = m_vulkanCaps.MaxTextureSize;
m_dynamicParameters.MaxColorTextureSamples = m_vulkanCaps.MaxColorTextureSamples;
m_dynamicParameters.MaxDepthTextureSamples = m_vulkanCaps.MaxDepthTextureSamples;
m_dynamicParameters.MaxFramebufferSamples = m_vulkanCaps.MaxFramebufferSamples;
m_dynamicParameters.MaxIntegerSamples = m_vulkanCaps.MaxIntegerSamples;
m_dynamicParameters.MaxSamples = m_vulkanCaps.MaxSamples;
m_dynamicParameters.MaxSampleMaskWords = m_vulkanCaps.MaxSampleMaskWords;
m_dynamicParameters.MaxTextureImageUnits = m_vulkanCaps.MaxTextureImageUnits;
m_dynamicParameters.MaxVertexTextureImageUnits = m_vulkanCaps.MaxVertexTextureImageUnits;
m_dynamicParameters.MaxComputeTextureImageUnits = m_vulkanCaps.MaxComputeTextureImageUnits;
m_dynamicParameters.MaxCombinedTextureImageUnits = m_vulkanCaps.MaxCombinedTextureImageUnits;
m_dynamicParameters.MaxVertexAttribs = m_vulkanCaps.MaxVertexAttribs;
m_dynamicParameters.MaxComputeShaderStorageBlocks = m_vulkanCaps.MaxComputeShaderStorageBlocks;
m_dynamicParameters.MaxCombinedShaderStorageBlocks = m_vulkanCaps.MaxCombinedShaderStorageBlocks;
m_dynamicParameters.MaxComputeUniformBlocks = m_vulkanCaps.MaxComputeUniformBlocks;
m_dynamicParameters.MaxComputeWorkGroupInvocations = m_vulkanCaps.MaxComputeWorkGroupInvocations;
m_dynamicParameters.MaxShaderStorageBufferBindings = m_vulkanCaps.MaxShaderStorageBufferBindings;
m_dynamicParameters.MaxTextureBufferSize = m_vulkanCaps.MaxTextureBufferSize;
m_dynamicParameters.MaxUniformBufferBindings = m_vulkanCaps.MaxUniformBufferBindings;
m_dynamicParameters.MaxUniformBlockSize = m_vulkanCaps.MaxUniformBlockSize;
m_dynamicParameters.MaxImageUnits = m_vulkanCaps.MaxImageUnits;
m_dynamicParameters.MaxCombinedImageUniforms = m_vulkanCaps.MaxCombinedImageUniforms;
m_dynamicParameters.MaxComputeImageUniforms = m_vulkanCaps.MaxComputeImageUniforms;
m_dynamicParameters.MaxDrawBuffers = m_vulkanCaps.MaxDrawBuffers;
m_dynamicParameters.MaxColorAttachments = m_vulkanCaps.MaxColorAttachments;
m_dynamicParameters.MaxClipDistances = m_vulkanCaps.MaxClipDistances;
m_dynamicParameters.MaxViewports = m_vulkanCaps.MaxViewports;
m_dynamicParameters.MaxViewportWidth = m_vulkanCaps.MaxViewportWidth;
m_dynamicParameters.MaxViewportHeight = m_vulkanCaps.MaxViewportHeight;
m_dynamicParameters.ViewportBoundsRangeMin = m_vulkanCaps.ViewportBoundsRangeMin;
m_dynamicParameters.ViewportBoundsRangeMax = m_vulkanCaps.ViewportBoundsRangeMax;
m_dynamicParameters.ViewportSubpixelBits = m_vulkanCaps.ViewportSubpixelBits;
m_dynamicParameters.SupportsWideLines = m_vulkanCaps.SupportsWideLines;
m_dynamicParameters.MaxShaderStorageBlockSize = m_dynamicParameters.MaxShaderStorageBlockSize =
std::min(m_vulkanCaps.MaxShaderStorageBlockSize, kMaxAdvertisedShaderStorageBlockSize); std::min(m_vulkanCaps.MaxShaderStorageBlockSize, kMaxAdvertisedShaderStorageBlockSize);
if (m_vulkanCaps.SupportsShaderSubgroup) { if (m_vulkanCaps.SupportsShaderSubgroup) {
+521 -33
View File
@@ -39,6 +39,21 @@ namespace MobileGL::MG_Backend::DirectVulkan {
GLint computeWorkGroupSize[3] = {1, 1, 1}; GLint computeWorkGroupSize[3] = {1, 1, 1};
}; };
struct DrawElementsIndirectCommand {
Uint32 count = 0;
Uint32 instanceCount = 0;
Uint32 firstIndex = 0;
Int32 baseVertex = 0;
Uint32 baseInstance = 0;
};
struct DrawArraysIndirectCommand {
Uint32 count = 0;
Uint32 instanceCount = 0;
Uint32 first = 0;
Uint32 baseInstance = 0;
};
UnorderedMap<GLuint, ProgramResourceCache> g_programResourceCaches; UnorderedMap<GLuint, ProgramResourceCache> g_programResourceCaches;
String NormalizeDescriptorName(const SpvReflectDescriptorBinding& binding) { String NormalizeDescriptorName(const SpvReflectDescriptorBinding& binding) {
@@ -193,6 +208,122 @@ namespace MobileGL::MG_Backend::DirectVulkan {
name[copyLength] = '\0'; name[copyLength] = '\0';
} }
} }
const Uint8* ResolveIndirectCommandBytes(const void* indirect, SizeT requiredBytes, const char* label) {
auto drawBuffer = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
if (drawBuffer) {
drawBuffer->MarkPersistentMappedRangeDirty();
const auto drawData = drawBuffer->GetDataReadOnly();
const SizeT commandOffset = reinterpret_cast<SizeT>(indirect);
if (!drawData || commandOffset + requiredBytes > drawData->size()) {
MGLOG_E("%s skipped: invalid GL_DRAW_INDIRECT_BUFFER binding or range", label);
return nullptr;
}
return drawData->data() + commandOffset;
}
if (!indirect) {
MGLOG_E("%s skipped: indirect pointer is null", label);
return nullptr;
}
return reinterpret_cast<const Uint8*>(indirect);
}
Vector<GLuint> GetUniformBlockActiveVariables(const MG_State::GLState::ProgramObject& program,
GLuint blockIndex) {
Vector<GLuint> activeVariables;
const Uint uniformCount = program.GetUniformCount();
activeVariables.reserve(uniformCount);
for (Uint uniformIndex = 0; uniformIndex < uniformCount; ++uniformIndex) {
if (program.GetActiveUniformBlockIndex(uniformIndex) == static_cast<Int>(blockIndex)) {
activeVariables.push_back(uniformIndex);
}
}
return activeVariables;
}
GLuint FindProgramInputIndex(const MG_State::GLState::ProgramObject& program, const String& name) {
const Int activeCount = program.GetActiveAttributesCount();
for (Int index = 0; index < activeCount; ++index) {
if (program.GetActiveAttribName(index) == name) {
return static_cast<GLuint>(index);
}
}
return GL_INVALID_INDEX;
}
GLuint FindProgramOutputIndex(const MG_State::GLState::ProgramObject& program, const String& name) {
const Int activeCount = program.GetActiveFragmentOutputCount();
for (Int index = 0; index < activeCount; ++index) {
if (program.GetActiveFragmentOutputName(index) == name) {
return static_cast<GLuint>(index);
}
}
return GL_INVALID_INDEX;
}
GLint GetProgramOutputLocation(const MG_State::GLState::ProgramObject& program, const String& name) {
const Int activeCount = program.GetActiveFragmentOutputCount();
for (Int index = 0; index < activeCount; ++index) {
if (program.GetActiveFragmentOutputName(index) == name) {
return program.GetFragmentOutputLocation(index);
}
}
return -1;
}
GLint GetProgramResourceActiveCount(const MG_State::GLState::ProgramObject& program, GLenum programInterface,
const ProgramResourceCache& cache) {
switch (programInterface) {
case GL_SHADER_STORAGE_BLOCK:
return static_cast<GLint>(cache.storageBlocks.size());
case GL_BUFFER_VARIABLE:
return static_cast<GLint>(cache.bufferVariables.size());
case GL_UNIFORM_BLOCK:
return program.GetActiveUniformBlocksCount();
case GL_UNIFORM:
return static_cast<GLint>(program.GetUniformCount());
case GL_PROGRAM_INPUT:
return program.GetActiveAttributesCount();
case GL_PROGRAM_OUTPUT:
return program.GetActiveFragmentOutputCount();
default:
return 0;
}
}
GLint GetProgramResourceMaxNameLength(const MG_State::GLState::ProgramObject& program, GLenum programInterface,
const ProgramResourceCache& cache) {
switch (programInterface) {
case GL_SHADER_STORAGE_BLOCK: {
SizeT maxLength = 0;
for (const auto& block : cache.storageBlocks) maxLength = std::max(maxLength, block.name.size() + 1);
return static_cast<GLint>(maxLength);
}
case GL_BUFFER_VARIABLE: {
SizeT maxLength = 0;
for (const auto& var : cache.bufferVariables) maxLength = std::max(maxLength, var.name.size() + 1);
return static_cast<GLint>(maxLength);
}
case GL_UNIFORM_BLOCK:
return program.GetActiveUniformBlocksMaxNameLength() + 1;
case GL_UNIFORM:
return program.GetUniformMaxLength() + 1;
case GL_PROGRAM_INPUT:
return program.GetActiveAttributesMaxLength() + 1;
case GL_PROGRAM_OUTPUT: {
SizeT maxLength = 0;
const Int activeCount = program.GetActiveFragmentOutputCount();
for (Int index = 0; index < activeCount; ++index) {
maxLength = std::max(maxLength, program.GetActiveFragmentOutputName(index).size() + 1);
}
return static_cast<GLint>(maxLength);
}
default:
return 0;
}
}
} // namespace } // namespace
GLuint GetShaderStorageBlockIndex(const MG_State::GLState::ProgramObject& program, const String& name) { GLuint GetShaderStorageBlockIndex(const MG_State::GLState::ProgramObject& program, const String& name) {
@@ -256,7 +387,44 @@ namespace MobileGL::MG_Backend::DirectVulkan {
pVulkanRenderer->MultiDrawElementsIndirectCount(mode, type, indirect, 0, drawcount, stride); pVulkanRenderer->MultiDrawElementsIndirectCount(mode, type, indirect, 0, drawcount, stride);
} }
void MultiDrawArraysIndirect(GLenum mode, const void* indirect, GLsizei drawcount, GLsizei stride) { void MultiDrawArraysIndirect(GLenum mode, const void* indirect, GLsizei drawcount, GLsizei stride) {
MGLOG_W("DirectVulkan::MultiDrawArraysIndirect is not implemented yet (drawcount=%d)", drawcount); MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::MultiDrawArraysIndirect called with null VulkanRenderer");
MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::MultiDrawArraysIndirect called with null GL context");
if (drawcount <= 0) {
return;
}
if (stride == 0) {
stride = sizeof(DrawArraysIndirectCommand);
}
if (stride < static_cast<GLsizei>(sizeof(DrawArraysIndirectCommand))) {
MGLOG_E("MultiDrawArraysIndirect skipped: stride %d is smaller than command size %zu",
stride, sizeof(DrawArraysIndirectCommand));
return;
}
const auto* commandBytes = ResolveIndirectCommandBytes(
indirect,
static_cast<SizeT>(stride) * static_cast<SizeT>(drawcount - 1) + sizeof(DrawArraysIndirectCommand),
"MultiDrawArraysIndirect");
if (!commandBytes) {
return;
}
for (GLsizei i = 0; i < drawcount; ++i) {
DrawArraysIndirectCommand cmd{};
std::memcpy(&cmd, commandBytes + static_cast<SizeT>(i) * stride, sizeof(cmd));
if (cmd.count == 0 || cmd.instanceCount == 0) {
continue;
}
DrawCmd payload{};
payload.mode = mode;
payload.params.vertexCount = cmd.count;
payload.params.instanceCount = cmd.instanceCount;
payload.params.firstVertex = cmd.first;
payload.params.firstInstance = cmd.baseInstance;
pVulkanRenderer->DrawArrays(payload);
}
} }
void MultiDrawElementsIndirectCount(GLenum mode, GLenum type, const void* indirect, GLintptr drawcount, void MultiDrawElementsIndirectCount(GLenum mode, GLenum type, const void* indirect, GLintptr drawcount,
GLsizei maxdrawcount, GLsizei stride) { GLsizei maxdrawcount, GLsizei stride) {
@@ -266,23 +434,152 @@ namespace MobileGL::MG_Backend::DirectVulkan {
} }
void MultiDrawArraysIndirectCount(GLenum mode, const void* indirect, GLintptr drawcount, void MultiDrawArraysIndirectCount(GLenum mode, const void* indirect, GLintptr drawcount,
GLsizei maxdrawcount, GLsizei stride) { GLsizei maxdrawcount, GLsizei stride) {
MGLOG_W("DirectVulkan::MultiDrawArraysIndirectCount is not implemented yet (maxdrawcount=%d)", maxdrawcount); MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::MultiDrawArraysIndirectCount called with null VulkanRenderer");
MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::MultiDrawArraysIndirectCount called with null GL context");
if (maxdrawcount <= 0) {
return;
}
if (stride == 0) {
stride = sizeof(DrawArraysIndirectCommand);
}
if (stride < static_cast<GLsizei>(sizeof(DrawArraysIndirectCommand))) {
MGLOG_E("MultiDrawArraysIndirectCount skipped: stride %d is smaller than command size %zu",
stride, sizeof(DrawArraysIndirectCommand));
return;
}
auto parameterBuffer = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::Parameter).GetBoundObject();
if (!parameterBuffer || drawcount < 0 || static_cast<SizeT>(drawcount) + sizeof(Uint32) > parameterBuffer->GetSize()) {
MGLOG_E("MultiDrawArraysIndirectCount skipped: invalid GL_PARAMETER_BUFFER binding or range");
return;
}
parameterBuffer->MarkPersistentMappedRangeDirty();
const auto parameterData = parameterBuffer->GetDataReadOnly();
if (!parameterData) {
MGLOG_E("MultiDrawArraysIndirectCount skipped: CPU fallback cannot read parameter buffer");
return;
}
Uint32 actualDrawCount = 0;
std::memcpy(&actualDrawCount, parameterData->data() + drawcount, sizeof(actualDrawCount));
actualDrawCount = std::min<Uint32>(actualDrawCount, static_cast<Uint32>(maxdrawcount));
MultiDrawArraysIndirect(mode, indirect, static_cast<GLsizei>(actualDrawCount), stride);
} }
void DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, void DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type,
const void* indices, GLint basevertex) {} const void* indices, GLint basevertex) {
void DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices) {} (void)start;
(void)end;
DrawElementsBaseVertex(mode, count, type, indices, basevertex);
}
void DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices) {
(void)start;
(void)end;
DrawElements(mode, count, type, indices);
}
void DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices, void DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices,
GLsizei instancecount, GLint basevertex, GLuint baseinstance) {} GLsizei instancecount, GLint basevertex, GLuint baseinstance) {
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawElementsInstancedBaseVertexBaseInstance called with null VulkanRenderer");
MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::DrawElementsInstancedBaseVertexBaseInstance called with null GL context");
DrawIndexedCmd payload{};
payload.mode = mode;
payload.indexBufferView.indexType = type;
payload.indexBufferView.indexByteOffset = reinterpret_cast<SizeT>(indices);
payload.indexBufferView.indexByteSize = count * MG_Util::GetGLTypeSize(type);
payload.params.indexCount = count;
payload.params.instanceCount = instancecount;
payload.params.firstIndex = 0;
payload.params.vertexOffset = basevertex;
payload.params.firstInstance = static_cast<Int32>(baseinstance);
pVulkanRenderer->DrawElements(payload);
}
void DrawElementsInstancedBaseVertex(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) {
DrawElementsInstancedBaseVertexBaseInstance(mode, count, type, indices, instancecount, basevertex, 0);
}
void DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices, void DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices,
GLsizei instancecount, GLuint baseinstance) {} GLsizei instancecount, GLuint baseinstance) {
void DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instancecount) {} DrawElementsInstancedBaseVertexBaseInstance(mode, count, type, indices, instancecount, 0, baseinstance);
void DrawElementsIndirect(GLenum mode, GLenum type, const void* indirect) {} }
void DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instancecount) {
DrawElementsInstancedBaseVertexBaseInstance(mode, count, type, indices, instancecount, 0, 0);
}
void DrawElementsIndirect(GLenum mode, GLenum type, const void* indirect) {
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawElementsIndirect called with null VulkanRenderer");
MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::DrawElementsIndirect called with null GL context");
const SizeT indexSize = MG_Util::GetGLTypeSize(type);
if (indexSize == 0) {
MGLOG_E("DrawElementsIndirect skipped: unsupported index type 0x%x", type);
return;
}
const auto* commandBytes =
ResolveIndirectCommandBytes(indirect, sizeof(DrawElementsIndirectCommand), "DrawElementsIndirect");
if (!commandBytes) {
return;
}
DrawElementsIndirectCommand cmd{};
std::memcpy(&cmd, commandBytes, sizeof(cmd));
if (cmd.count == 0 || cmd.instanceCount == 0) {
return;
}
DrawIndexedCmd payload{};
payload.mode = mode;
payload.indexBufferView.indexType = type;
payload.indexBufferView.indexByteOffset = static_cast<SizeT>(cmd.firstIndex) * indexSize;
payload.indexBufferView.indexByteSize = static_cast<SizeT>(cmd.count) * indexSize;
payload.params.indexCount = cmd.count;
payload.params.instanceCount = cmd.instanceCount;
payload.params.firstIndex = 0;
payload.params.vertexOffset = cmd.baseVertex;
payload.params.firstInstance = static_cast<Int32>(cmd.baseInstance);
pVulkanRenderer->DrawElements(payload);
}
void DrawArraysInstancedBaseInstance(GLenum mode, GLint first, GLsizei count, GLsizei instancecount, void DrawArraysInstancedBaseInstance(GLenum mode, GLint first, GLsizei count, GLsizei instancecount,
GLuint baseinstance) {} GLuint baseinstance) {
void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount) {} MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawArraysInstancedBaseInstance called with null VulkanRenderer");
void DrawArraysIndirect(GLenum mode, const void* indirect) {} MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::DrawArraysInstancedBaseInstance called with null GL context");
DrawCmd payload{};
payload.mode = mode;
payload.params.vertexCount = count;
payload.params.instanceCount = instancecount;
payload.params.firstVertex = first;
payload.params.firstInstance = baseinstance;
pVulkanRenderer->DrawArrays(payload);
}
void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount) {
DrawArraysInstancedBaseInstance(mode, first, count, instancecount, 0);
}
void DrawArraysIndirect(GLenum mode, const void* indirect) {
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawArraysIndirect called with null VulkanRenderer");
MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::DrawArraysIndirect called with null GL context");
const auto* commandBytes =
ResolveIndirectCommandBytes(indirect, sizeof(DrawArraysIndirectCommand), "DrawArraysIndirect");
if (!commandBytes) {
return;
}
DrawArraysIndirectCommand cmd{};
std::memcpy(&cmd, commandBytes, sizeof(cmd));
if (cmd.count == 0 || cmd.instanceCount == 0) {
return;
}
DrawCmd payload{};
payload.mode = mode;
payload.params.vertexCount = cmd.count;
payload.params.instanceCount = cmd.instanceCount;
payload.params.firstVertex = cmd.first;
payload.params.firstInstance = cmd.baseInstance;
pVulkanRenderer->DrawArrays(payload);
}
void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width,
GLsizei height, GLint border) { GLsizei height, GLint border) {
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::CopyTexImage2D called with null VulkanRenderer"); MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::CopyTexImage2D called with null VulkanRenderer");
@@ -461,31 +758,35 @@ namespace MobileGL::MG_Backend::DirectVulkan {
auto* programObject = TryGetDirectVulkanProgram(program); auto* programObject = TryGetDirectVulkanProgram(program);
if (!programObject) return; if (!programObject) return;
auto& cache = GetProgramResourceCache(*programObject); auto& cache = GetProgramResourceCache(*programObject);
switch (pname) {
case GL_ACTIVE_RESOURCES:
*params = GetProgramResourceActiveCount(*programObject, programInterface, cache);
return;
case GL_MAX_NAME_LENGTH:
*params = GetProgramResourceMaxNameLength(*programObject, programInterface, cache);
return;
case GL_MAX_NUM_ACTIVE_VARIABLES:
if (programInterface == GL_SHADER_STORAGE_BLOCK) { if (programInterface == GL_SHADER_STORAGE_BLOCK) {
if (pname == GL_ACTIVE_RESOURCES) { SizeT maxCount = 0;
*params = static_cast<GLint>(cache.storageBlocks.size()); for (const auto& block : cache.storageBlocks) {
} else if (pname == GL_MAX_NAME_LENGTH) { maxCount = std::max(maxCount, block.activeVariables.size());
SizeT maxLength = 0; }
for (const auto& block : cache.storageBlocks) maxLength = std::max(maxLength, block.name.size() + 1); *params = static_cast<GLint>(maxCount);
*params = static_cast<GLint>(maxLength); } else if (programInterface == GL_UNIFORM_BLOCK) {
GLint maxCount = 0;
const Int activeBlocks = programObject->GetActiveUniformBlocksCount();
for (Int index = 0; index < activeBlocks; ++index) {
maxCount = std::max(maxCount, programObject->GetUniformBlockActiveUniformCount(index));
}
*params = maxCount;
} else { } else {
*params = 0; *params = 0;
} }
return; return;
} default:
if (programInterface == GL_BUFFER_VARIABLE) {
if (pname == GL_ACTIVE_RESOURCES) {
*params = static_cast<GLint>(cache.bufferVariables.size());
} else if (pname == GL_MAX_NAME_LENGTH) {
SizeT maxLength = 0;
for (const auto& var : cache.bufferVariables) maxLength = std::max(maxLength, var.name.size() + 1);
*params = static_cast<GLint>(maxLength);
} else {
*params = 0; *params = 0;
}
return; return;
} }
*params = 0;
} }
GLuint GetProgramResourceIndex(GLuint program, GLenum programInterface, const GLchar* name) { GLuint GetProgramResourceIndex(GLuint program, GLenum programInterface, const GLchar* name) {
@@ -493,17 +794,30 @@ namespace MobileGL::MG_Backend::DirectVulkan {
auto* programObject = TryGetDirectVulkanProgram(program); auto* programObject = TryGetDirectVulkanProgram(program);
if (!programObject) return GL_INVALID_INDEX; if (!programObject) return GL_INVALID_INDEX;
auto& cache = GetProgramResourceCache(*programObject); auto& cache = GetProgramResourceCache(*programObject);
const String resourceName = name;
if (programInterface == GL_SHADER_STORAGE_BLOCK) { if (programInterface == GL_SHADER_STORAGE_BLOCK) {
return GetShaderStorageBlockIndex(*programObject, name); return GetShaderStorageBlockIndex(*programObject, name);
} }
if (programInterface == GL_BUFFER_VARIABLE) { if (programInterface == GL_BUFFER_VARIABLE) {
const String resourceName = name;
const auto it = std::find_if(cache.bufferVariables.begin(), cache.bufferVariables.end(), const auto it = std::find_if(cache.bufferVariables.begin(), cache.bufferVariables.end(),
[&](const BufferVariableResource& var) { return var.name == resourceName; }); [&](const BufferVariableResource& var) { return var.name == resourceName; });
return it == cache.bufferVariables.end() return it == cache.bufferVariables.end()
? GL_INVALID_INDEX ? GL_INVALID_INDEX
: static_cast<GLuint>(std::distance(cache.bufferVariables.begin(), it)); : static_cast<GLuint>(std::distance(cache.bufferVariables.begin(), it));
} }
if (programInterface == GL_UNIFORM_BLOCK) {
return programObject->GetUniformBlockIndex(name);
}
if (programInterface == GL_UNIFORM) {
const Int activeUniformIndex = programObject->GetActiveUniformIndex(resourceName);
return activeUniformIndex >= 0 ? static_cast<GLuint>(activeUniformIndex) : GL_INVALID_INDEX;
}
if (programInterface == GL_PROGRAM_INPUT) {
return FindProgramInputIndex(*programObject, resourceName);
}
if (programInterface == GL_PROGRAM_OUTPUT) {
return FindProgramOutputIndex(*programObject, resourceName);
}
return GL_INVALID_INDEX; return GL_INVALID_INDEX;
} }
@@ -520,6 +834,23 @@ namespace MobileGL::MG_Backend::DirectVulkan {
CopyResourceName(cache.bufferVariables[index].name, bufSize, length, name); CopyResourceName(cache.bufferVariables[index].name, bufSize, length, name);
return; return;
} }
if (programInterface == GL_UNIFORM_BLOCK && programObject->IsActiveUniformBlock(index)) {
CopyResourceName(programObject->GetUniformBlockName(index), bufSize, length, name);
return;
}
if (programInterface == GL_UNIFORM && index < programObject->GetUniformCount()) {
CopyResourceName(programObject->GetActiveUniformName(index), bufSize, length, name);
return;
}
if (programInterface == GL_PROGRAM_INPUT && index < static_cast<GLuint>(programObject->GetActiveAttributesCount())) {
CopyResourceName(programObject->GetActiveAttribName(index), bufSize, length, name);
return;
}
if (programInterface == GL_PROGRAM_OUTPUT &&
index < static_cast<GLuint>(programObject->GetActiveFragmentOutputCount())) {
CopyResourceName(programObject->GetActiveFragmentOutputName(index), bufSize, length, name);
return;
}
if (length) *length = 0; if (length) *length = 0;
if (name && bufSize > 0) name[0] = '\0'; if (name && bufSize > 0) name[0] = '\0';
} }
@@ -589,6 +920,155 @@ namespace MobileGL::MG_Backend::DirectVulkan {
writeValue(0); writeValue(0);
break; break;
} }
} else if (programInterface == GL_UNIFORM_BLOCK &&
programObject->IsActiveUniformBlock(index)) {
const auto activeVariables = GetUniformBlockActiveVariables(*programObject, index);
switch (prop) {
case GL_NAME_LENGTH:
writeValue(static_cast<GLint>(programObject->GetUniformBlockName(index).size() + 1));
break;
case GL_BUFFER_BINDING:
writeValue(static_cast<GLint>(programObject->GetUniformBlockBinding(index)));
break;
case GL_BUFFER_DATA_SIZE:
writeValue(static_cast<GLint>(programObject->GetUBOSizeAt(index)));
break;
case GL_NUM_ACTIVE_VARIABLES:
writeValue(static_cast<GLint>(activeVariables.size()));
break;
case GL_ACTIVE_VARIABLES:
for (const GLuint variableIndex : activeVariables) {
writeValue(static_cast<GLint>(variableIndex));
}
break;
case GL_REFERENCED_BY_VERTEX_SHADER:
writeValue(programObject->IsUniformBlockReferencedByStage(index, EShLangVertex) ? GL_TRUE
: GL_FALSE);
break;
case GL_REFERENCED_BY_FRAGMENT_SHADER:
writeValue(programObject->IsUniformBlockReferencedByStage(index, EShLangFragment) ? GL_TRUE
: GL_FALSE);
break;
case GL_REFERENCED_BY_COMPUTE_SHADER:
writeValue(programObject->IsUniformBlockReferencedByStage(index, EShLangCompute) ? GL_TRUE
: GL_FALSE);
break;
case GL_REFERENCED_BY_GEOMETRY_SHADER:
case GL_REFERENCED_BY_TESS_CONTROL_SHADER:
case GL_REFERENCED_BY_TESS_EVALUATION_SHADER:
writeValue(GL_FALSE);
break;
default:
writeValue(0);
break;
}
} else if (programInterface == GL_UNIFORM && index < programObject->GetUniformCount()) {
const auto& uniformName = programObject->GetActiveUniformName(index);
const GLint location = programObject->GetUniformLocation(uniformName);
switch (prop) {
case GL_NAME_LENGTH:
writeValue(static_cast<GLint>(uniformName.size() + 1));
break;
case GL_TYPE:
writeValue(static_cast<GLint>(programObject->GetActiveUniformType(index)));
break;
case GL_ARRAY_SIZE:
writeValue(programObject->GetActiveUniformArraySize(index));
break;
case GL_BLOCK_INDEX:
writeValue(programObject->GetActiveUniformBlockIndex(index));
break;
case GL_LOCATION:
writeValue(location);
break;
case GL_OFFSET:
writeValue(location >= 0 && programObject->IsValidUniformLocation(location)
? static_cast<GLint>(programObject->GetUniformOffset(location))
: 0);
break;
case GL_ARRAY_STRIDE:
case GL_MATRIX_STRIDE:
case GL_IS_ROW_MAJOR:
case GL_TOP_LEVEL_ARRAY_SIZE:
case GL_TOP_LEVEL_ARRAY_STRIDE:
case GL_REFERENCED_BY_VERTEX_SHADER:
case GL_REFERENCED_BY_FRAGMENT_SHADER:
case GL_REFERENCED_BY_COMPUTE_SHADER:
case GL_REFERENCED_BY_GEOMETRY_SHADER:
case GL_REFERENCED_BY_TESS_CONTROL_SHADER:
case GL_REFERENCED_BY_TESS_EVALUATION_SHADER:
writeValue(0);
break;
default:
writeValue(0);
break;
}
} else if (programInterface == GL_PROGRAM_INPUT &&
index < static_cast<GLuint>(programObject->GetActiveAttributesCount())) {
const auto& resourceName = programObject->GetActiveAttribName(index);
switch (prop) {
case GL_NAME_LENGTH:
writeValue(static_cast<GLint>(resourceName.size() + 1));
break;
case GL_TYPE:
writeValue(static_cast<GLint>(programObject->GetActiveAttribType(index)));
break;
case GL_ARRAY_SIZE:
writeValue(programObject->GetActiveAttribArraySize(index));
break;
case GL_LOCATION:
writeValue(programObject->GetAttributeLocation(resourceName));
break;
case GL_REFERENCED_BY_VERTEX_SHADER:
writeValue(GL_TRUE);
break;
case GL_REFERENCED_BY_FRAGMENT_SHADER:
case GL_REFERENCED_BY_COMPUTE_SHADER:
case GL_REFERENCED_BY_GEOMETRY_SHADER:
case GL_REFERENCED_BY_TESS_CONTROL_SHADER:
case GL_REFERENCED_BY_TESS_EVALUATION_SHADER:
case GL_IS_PER_PATCH:
case GL_LOCATION_INDEX:
writeValue(0);
break;
default:
writeValue(0);
break;
}
} else if (programInterface == GL_PROGRAM_OUTPUT &&
index < static_cast<GLuint>(programObject->GetActiveFragmentOutputCount())) {
const auto& resourceName = programObject->GetActiveFragmentOutputName(index);
switch (prop) {
case GL_NAME_LENGTH:
writeValue(static_cast<GLint>(resourceName.size() + 1));
break;
case GL_TYPE:
writeValue(static_cast<GLint>(programObject->GetFragmentOutputType(index)));
break;
case GL_ARRAY_SIZE:
writeValue(programObject->GetActiveFragmentOutputArraySize(index));
break;
case GL_LOCATION:
writeValue(programObject->GetFragmentOutputLocation(index));
break;
case GL_LOCATION_INDEX:
writeValue(0);
break;
case GL_REFERENCED_BY_FRAGMENT_SHADER:
writeValue(GL_TRUE);
break;
case GL_REFERENCED_BY_VERTEX_SHADER:
case GL_REFERENCED_BY_COMPUTE_SHADER:
case GL_REFERENCED_BY_GEOMETRY_SHADER:
case GL_REFERENCED_BY_TESS_CONTROL_SHADER:
case GL_REFERENCED_BY_TESS_EVALUATION_SHADER:
case GL_IS_PER_PATCH:
writeValue(0);
break;
default:
writeValue(0);
break;
}
} else { } else {
writeValue(0); writeValue(0);
} }
@@ -602,13 +1082,21 @@ namespace MobileGL::MG_Backend::DirectVulkan {
if (programInterface == GL_UNIFORM) { if (programInterface == GL_UNIFORM) {
return programObject->GetUniformLocation(name); return programObject->GetUniformLocation(name);
} }
if (programInterface == GL_PROGRAM_INPUT) {
return programObject->GetAttributeLocation(name);
}
if (programInterface == GL_PROGRAM_OUTPUT) {
return GetProgramOutputLocation(*programObject, name);
}
return -1; return -1;
} }
GLint GetProgramResourceLocationIndex(GLuint program, GLenum programInterface, const GLchar* name) { GLint GetProgramResourceLocationIndex(GLuint program, GLenum programInterface, const GLchar* name) {
(void)program; auto* programObject = TryGetDirectVulkanProgram(program);
(void)programInterface; if (!programObject || !name) return -1;
(void)name; if (programInterface == GL_PROGRAM_OUTPUT) {
return GetProgramOutputLocation(*programObject, name) >= 0 ? 0 : -1;
}
return -1; return -1;
} }
@@ -188,18 +188,18 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return packet; return packet;
} }
FrameContext::PresentInfoPacket FrameContext::GetPresentInfo(VkSwapchainKHR swapchain, const Uint32& imageIndex) const { FrameContext::PresentInfoPacket FrameContext::GetPresentInfo(VkSwapchainKHR swapchain, Uint32 imageIndex) const {
AssertValidSwapchainImageIndex(imageIndex); AssertValidSwapchainImageIndex(imageIndex);
PresentInfoPacket packet{}; PresentInfoPacket packet{};
packet.waitSemaphore = m_swapchainImageRenderFinishedSemaphores[imageIndex]; packet.waitSemaphore = m_swapchainImageRenderFinishedSemaphores[imageIndex];
packet.swapchain = swapchain; packet.swapchain = swapchain;
packet.imageIndex = &imageIndex; packet.imageIndex = imageIndex;
packet.presentInfo.waitSemaphoreCount = 1; packet.presentInfo.waitSemaphoreCount = 1;
packet.presentInfo.pWaitSemaphores = &packet.waitSemaphore; packet.presentInfo.pWaitSemaphores = &packet.waitSemaphore;
packet.presentInfo.swapchainCount = 1; packet.presentInfo.swapchainCount = 1;
packet.presentInfo.pSwapchains = &packet.swapchain; packet.presentInfo.pSwapchains = &packet.swapchain;
packet.presentInfo.pImageIndices = packet.imageIndex; packet.presentInfo.pImageIndices = &packet.imageIndex;
packet.presentInfo.pResults = nullptr; packet.presentInfo.pResults = nullptr;
return packet; return packet;
} }
@@ -212,14 +212,14 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return result; return result;
} }
result = vkResetFences(device, 1, &frame.imageInFlightFence); result = vkAcquireNextImageKHR(device, swapchain, timeout, frame.imageAvailableSemaphore, acquireFence,
&outImageIndex);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
return result; return result;
} }
frame.imageAvailableSemaphoreConsumed = false; frame.imageAvailableSemaphoreConsumed = false;
return vkAcquireNextImageKHR(device, swapchain, timeout, frame.imageAvailableSemaphore, acquireFence, return vkResetFences(device, 1, &frame.imageInFlightFence);
&outImageIndex);
} }
Uint32 FrameContext::GetCurrentFrameIndex() const { Uint32 FrameContext::GetCurrentFrameIndex() const {
@@ -25,7 +25,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
struct PresentInfoPacket { struct PresentInfoPacket {
VkSemaphore waitSemaphore = VK_NULL_HANDLE; VkSemaphore waitSemaphore = VK_NULL_HANDLE;
VkSwapchainKHR swapchain = VK_NULL_HANDLE; VkSwapchainKHR swapchain = VK_NULL_HANDLE;
const Uint32* imageIndex = nullptr; Uint32 imageIndex = 0;
VkPresentInfoKHR presentInfo{VK_STRUCTURE_TYPE_PRESENT_INFO_KHR}; VkPresentInfoKHR presentInfo{VK_STRUCTURE_TYPE_PRESENT_INFO_KHR};
}; };
@@ -54,7 +54,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Bool TransitionToPresent(VkImage image, VkImageLayout oldLayout, Bool TransitionToPresent(VkImage image, VkImageLayout oldLayout,
VkImageLayout presentLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); VkImageLayout presentLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
SubmitInfoPacket GetSubmitInfo(Bool shouldSubmitCommandBuffer, Uint32 swapchainImageIndex) const; SubmitInfoPacket GetSubmitInfo(Bool shouldSubmitCommandBuffer, Uint32 swapchainImageIndex) const;
PresentInfoPacket GetPresentInfo(VkSwapchainKHR swapchain, const Uint32& imageIndex) const; PresentInfoPacket GetPresentInfo(VkSwapchainKHR swapchain, Uint32 imageIndex) const;
VkResult WaitAndAcquireNextImage(VkDevice device, VkSwapchainKHR swapchain, Uint32& outImageIndex, VkResult WaitAndAcquireNextImage(VkDevice device, VkSwapchainKHR swapchain, Uint32& outImageIndex,
Uint64 timeout = UINT64_MAX, VkFence acquireFence = VK_NULL_HANDLE); Uint64 timeout = UINT64_MAX, VkFence acquireFence = VK_NULL_HANDLE);
@@ -33,13 +33,32 @@ namespace MobileGL::MG_Backend::DirectVulkan {
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.pipelineLayout, sizeof(payload.pipelineLayout))); XXHASH_VERIFY(XXH64_update(m_hashState, &payload.pipelineLayout, sizeof(payload.pipelineLayout)));
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.renderPass, sizeof(payload.renderPass))); XXHASH_VERIFY(XXH64_update(m_hashState, &payload.renderPass, sizeof(payload.renderPass)));
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.colorAttachmentCount, sizeof(payload.colorAttachmentCount))); XXHASH_VERIFY(XXH64_update(m_hashState, &payload.colorAttachmentCount, sizeof(payload.colorAttachmentCount)));
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.rasterizationSamples, sizeof(payload.rasterizationSamples)));
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.subpass, sizeof(payload.subpass))); XXHASH_VERIFY(XXH64_update(m_hashState, &payload.subpass, sizeof(payload.subpass)));
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.topology, sizeof(payload.topology))); XXHASH_VERIFY(XXH64_update(m_hashState, &payload.topology, sizeof(payload.topology)));
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.cullMode, sizeof(payload.cullMode))); XXHASH_VERIFY(XXH64_update(m_hashState, &payload.cullMode, sizeof(payload.cullMode)));
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.frontFace, sizeof(payload.frontFace))); XXHASH_VERIFY(XXH64_update(m_hashState, &payload.frontFace, sizeof(payload.frontFace)));
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.depthTestEnable, sizeof(payload.depthTestEnable))); XXHASH_VERIFY(XXH64_update(m_hashState, &payload.depthTestEnable, sizeof(payload.depthTestEnable)));
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.depthWriteEnable, sizeof(payload.depthWriteEnable))); XXHASH_VERIFY(XXH64_update(m_hashState, &payload.depthWriteEnable, sizeof(payload.depthWriteEnable)));
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.depthBiasEnable, sizeof(payload.depthBiasEnable)));
XXHASH_VERIFY(
XXH64_update(m_hashState, &payload.rasterizerDiscardEnable, sizeof(payload.rasterizerDiscardEnable)));
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.logicOpEnable, sizeof(payload.logicOpEnable)));
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.stencilTestEnable, sizeof(payload.stencilTestEnable)));
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.depthCompareOp, sizeof(payload.depthCompareOp))); XXHASH_VERIFY(XXH64_update(m_hashState, &payload.depthCompareOp, sizeof(payload.depthCompareOp)));
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.logicOp, sizeof(payload.logicOp)));
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.frontStencilFailOp, sizeof(payload.frontStencilFailOp)));
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.frontStencilPassOp, sizeof(payload.frontStencilPassOp)));
XXHASH_VERIFY(
XXH64_update(m_hashState, &payload.frontStencilDepthFailOp, sizeof(payload.frontStencilDepthFailOp)));
XXHASH_VERIFY(
XXH64_update(m_hashState, &payload.frontStencilCompareOp, sizeof(payload.frontStencilCompareOp)));
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.backStencilFailOp, sizeof(payload.backStencilFailOp)));
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.backStencilPassOp, sizeof(payload.backStencilPassOp)));
XXHASH_VERIFY(
XXH64_update(m_hashState, &payload.backStencilDepthFailOp, sizeof(payload.backStencilDepthFailOp)));
XXHASH_VERIFY(
XXH64_update(m_hashState, &payload.backStencilCompareOp, sizeof(payload.backStencilCompareOp)));
if (payload.colorAttachmentCount > 0) { if (payload.colorAttachmentCount > 0) {
XXHASH_VERIFY(XXH64_update( XXHASH_VERIFY(XXH64_update(
m_hashState, m_hashState,
@@ -86,7 +105,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
static constexpr VkDynamicState kDynamicStates[] = { static constexpr VkDynamicState kDynamicStates[] = {
VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR VK_DYNAMIC_STATE_SCISSOR,
VK_DYNAMIC_STATE_BLEND_CONSTANTS,
VK_DYNAMIC_STATE_DEPTH_BIAS,
VK_DYNAMIC_STATE_LINE_WIDTH,
VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
VK_DYNAMIC_STATE_STENCIL_REFERENCE
}; };
VkPipelineDynamicStateCreateInfo dynamicState{}; VkPipelineDynamicStateCreateInfo dynamicState{};
@@ -105,23 +130,43 @@ namespace MobileGL::MG_Backend::DirectVulkan {
raster.polygonMode = VK_POLYGON_MODE_FILL; raster.polygonMode = VK_POLYGON_MODE_FILL;
raster.cullMode = payload.cullMode; raster.cullMode = payload.cullMode;
raster.frontFace = payload.frontFace; raster.frontFace = payload.frontFace;
raster.depthBiasEnable = payload.depthBiasEnable ? VK_TRUE : VK_FALSE;
raster.rasterizerDiscardEnable = payload.rasterizerDiscardEnable ? VK_TRUE : VK_FALSE;
raster.lineWidth = 1.0f; raster.lineWidth = 1.0f;
VkPipelineMultisampleStateCreateInfo ms{VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO}; VkPipelineMultisampleStateCreateInfo ms{VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO};
ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; ms.rasterizationSamples = payload.rasterizationSamples;
VkPipelineDepthStencilStateCreateInfo depthStencil{VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO}; VkPipelineDepthStencilStateCreateInfo depthStencil{VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO};
depthStencil.depthTestEnable = payload.depthTestEnable ? VK_TRUE : VK_FALSE; depthStencil.depthTestEnable = payload.depthTestEnable ? VK_TRUE : VK_FALSE;
depthStencil.depthWriteEnable = payload.depthWriteEnable ? VK_TRUE : VK_FALSE; depthStencil.depthWriteEnable = payload.depthWriteEnable ? VK_TRUE : VK_FALSE;
depthStencil.depthCompareOp = payload.depthCompareOp; depthStencil.depthCompareOp = payload.depthCompareOp;
depthStencil.depthBoundsTestEnable = VK_FALSE; depthStencil.depthBoundsTestEnable = VK_FALSE;
depthStencil.stencilTestEnable = VK_FALSE; depthStencil.stencilTestEnable = payload.stencilTestEnable ? VK_TRUE : VK_FALSE;
if (payload.stencilTestEnable) {
depthStencil.front.failOp = payload.frontStencilFailOp;
depthStencil.front.passOp = payload.frontStencilPassOp;
depthStencil.front.depthFailOp = payload.frontStencilDepthFailOp;
depthStencil.front.compareOp = payload.frontStencilCompareOp;
depthStencil.front.compareMask = 0xffffffffu;
depthStencil.front.writeMask = 0xffffffffu;
depthStencil.front.reference = 0;
depthStencil.back.failOp = payload.backStencilFailOp;
depthStencil.back.passOp = payload.backStencilPassOp;
depthStencil.back.depthFailOp = payload.backStencilDepthFailOp;
depthStencil.back.compareOp = payload.backStencilCompareOp;
depthStencil.back.compareMask = 0xffffffffu;
depthStencil.back.writeMask = 0xffffffffu;
depthStencil.back.reference = 0;
}
Vector<VkPipelineColorBlendAttachmentState> colorAttachments(payload.colorAttachmentCount); Vector<VkPipelineColorBlendAttachmentState> colorAttachments(payload.colorAttachmentCount);
for (Uint32 i = 0; i < payload.colorAttachmentCount; ++i) { for (Uint32 i = 0; i < payload.colorAttachmentCount; ++i) {
colorAttachments[i] = payload.colorBlendAttachments[i]; colorAttachments[i] = payload.colorBlendAttachments[i];
} }
VkPipelineColorBlendStateCreateInfo blend{VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO}; VkPipelineColorBlendStateCreateInfo blend{VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO};
blend.logicOpEnable = payload.logicOpEnable ? VK_TRUE : VK_FALSE;
blend.logicOp = payload.logicOp;
blend.attachmentCount = payload.colorAttachmentCount; blend.attachmentCount = payload.colorAttachmentCount;
blend.pAttachments = colorAttachments.empty() ? nullptr : colorAttachments.data(); blend.pAttachments = colorAttachments.empty() ? nullptr : colorAttachments.data();
@@ -26,13 +26,27 @@ namespace MobileGL::MG_Backend::DirectVulkan {
VkPipelineLayout pipelineLayout = VK_NULL_HANDLE; VkPipelineLayout pipelineLayout = VK_NULL_HANDLE;
VkRenderPass renderPass = VK_NULL_HANDLE; VkRenderPass renderPass = VK_NULL_HANDLE;
Uint32 colorAttachmentCount = 1; Uint32 colorAttachmentCount = 1;
VkSampleCountFlagBits rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
Uint32 subpass = 0; Uint32 subpass = 0;
VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
VkCullModeFlags cullMode = VK_CULL_MODE_BACK_BIT; VkCullModeFlags cullMode = VK_CULL_MODE_BACK_BIT;
VkFrontFace frontFace = VK_FRONT_FACE_CLOCKWISE; VkFrontFace frontFace = VK_FRONT_FACE_CLOCKWISE;
Bool depthTestEnable = false; Bool depthTestEnable = false;
Bool depthWriteEnable = false; Bool depthWriteEnable = false;
Bool depthBiasEnable = false;
Bool rasterizerDiscardEnable = false;
Bool logicOpEnable = false;
Bool stencilTestEnable = false;
VkCompareOp depthCompareOp = VK_COMPARE_OP_ALWAYS; VkCompareOp depthCompareOp = VK_COMPARE_OP_ALWAYS;
VkLogicOp logicOp = VK_LOGIC_OP_COPY;
VkStencilOp frontStencilFailOp = VK_STENCIL_OP_KEEP;
VkStencilOp frontStencilPassOp = VK_STENCIL_OP_KEEP;
VkStencilOp frontStencilDepthFailOp = VK_STENCIL_OP_KEEP;
VkCompareOp frontStencilCompareOp = VK_COMPARE_OP_ALWAYS;
VkStencilOp backStencilFailOp = VK_STENCIL_OP_KEEP;
VkStencilOp backStencilPassOp = VK_STENCIL_OP_KEEP;
VkStencilOp backStencilDepthFailOp = VK_STENCIL_OP_KEEP;
VkCompareOp backStencilCompareOp = VK_COMPARE_OP_ALWAYS;
Array<VkPipelineColorBlendAttachmentState, kMaxColorAttachments> colorBlendAttachments{}; Array<VkPipelineColorBlendAttachmentState, kMaxColorAttachments> colorBlendAttachments{};
const Vector<VkPipelineShaderStageCreateInfo>* stages = nullptr; const Vector<VkPipelineShaderStageCreateInfo>* stages = nullptr;
const VkPipelineVertexInputStateCreateInfo* vertexInputState = nullptr; const VkPipelineVertexInputStateCreateInfo* vertexInputState = nullptr;
@@ -153,7 +153,10 @@ namespace MobileGL::MG_Backend::DirectVulkan {
MGLOG_I("Picked present mode: %s", string_VkPresentModeKHR(presentMode)); MGLOG_I("Picked present mode: %s", string_VkPresentModeKHR(presentMode));
const auto& swapchainCaps = swapchainCapabilities.capabilities; const auto& swapchainCaps = swapchainCapabilities.capabilities;
const auto targetImageCount = std::max<Uint32>(minImageCountHint, swapchainCaps.minImageCount); Uint32 targetImageCount = std::max<Uint32>(minImageCountHint, swapchainCaps.minImageCount);
if (swapchainCaps.maxImageCount != 0) {
targetImageCount = std::min(targetImageCount, swapchainCaps.maxImageCount);
}
MGLOG_I("Set minImageCount = %u", targetImageCount); MGLOG_I("Set minImageCount = %u", targetImageCount);
MGLOG_I("Swapchain currentTransform = %s", MGLOG_I("Swapchain currentTransform = %s",
string_VkSurfaceTransformFlagBitsKHR(swapchainCaps.currentTransform)); string_VkSurfaceTransformFlagBitsKHR(swapchainCaps.currentTransform));
@@ -234,11 +237,16 @@ namespace MobileGL::MG_Backend::DirectVulkan {
// Properly initialize Default FBO here // Properly initialize Default FBO here
auto& defaultFBOInfo = MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo; auto& defaultFBOInfo = MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo;
const Int extentWidth = static_cast<Int>(createInfo.imageExtent.width);
const Int extentHeight = static_cast<Int>(createInfo.imageExtent.height);
const SizeT defaultAttachmentByteSize =
static_cast<SizeT>(createInfo.imageExtent.width) * static_cast<SizeT>(createInfo.imageExtent.height) * 4;
auto* colorTex = static_cast<MG_State::GLState::TextureObject2D*>(defaultFBOInfo->colorAttachment.get()); auto* colorTex = static_cast<MG_State::GLState::TextureObject2D*>(defaultFBOInfo->colorAttachment.get());
colorTex->AllocateStorage( colorTex->AllocateStorage(
TextureUploadTarget::Texture2D, 0, { TextureUploadTarget::Texture2D, 0, {
{(Int)createInfo.imageExtent.width, (Int)createInfo.imageExtent.height, 1}, {extentWidth, extentHeight, 1},
createInfo.imageExtent.width * (Int)createInfo.imageExtent.height * 4}); // TODO: 4 is format size defaultAttachmentByteSize}); // TODO: 4 is format size
TextureInternalFormat depthFormat = TextureInternalFormat::Depth24Stencil8; TextureInternalFormat depthFormat = TextureInternalFormat::Depth24Stencil8;
switch (m_depthStencilFormat) { switch (m_depthStencilFormat) {
case VK_FORMAT_D24_UNORM_S8_UINT: case VK_FORMAT_D24_UNORM_S8_UINT:
@@ -257,8 +265,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
auto* depthTex = static_cast<MG_State::GLState::TextureObject2D*>(defaultFBOInfo->depthAttachment.get()); auto* depthTex = static_cast<MG_State::GLState::TextureObject2D*>(defaultFBOInfo->depthAttachment.get());
depthTex->SetInternalFormat(depthFormat); depthTex->SetInternalFormat(depthFormat);
depthTex->AllocateStorage(TextureUploadTarget::Texture2D, 0, { depthTex->AllocateStorage(TextureUploadTarget::Texture2D, 0, {
{(Int)createInfo.imageExtent.width, (Int)createInfo.imageExtent.height, 1}, {extentWidth, extentHeight, 1},
createInfo.imageExtent.width * createInfo.imageExtent.width * 4}); // TODO: 4 is format size defaultAttachmentByteSize}); // TODO: 4 is format size
} }
@@ -12,7 +12,23 @@
#include "MG_Util/Converters/MGToStr/TextureEnumConverter.h" #include "MG_Util/Converters/MGToStr/TextureEnumConverter.h"
namespace MobileGL::MG_Backend::DirectVulkan { namespace MobileGL::MG_Backend::DirectVulkan {
static SharedPtr<MG_State::GLState::ITextureObject> GetClearableAttachmentTexture( static Bool IsCubeMapFaceUploadTarget(TextureUploadTarget target) {
return target >= TextureUploadTarget::CubeMapPositiveX &&
target <= TextureUploadTarget::CubeMapNegativeZ;
}
static Bool PendingClearMatchesTextureIdentity(const PendingClearKey& key, const TextureIdentity& identity) {
return key.texture == identity.texture && key.textureLifetimeId == identity.lifetimeId;
}
static Uint32 ResolveAttachmentBaseArrayLayer(TextureUploadTarget target) {
if (!IsCubeMapFaceUploadTarget(target)) {
return 0;
}
return static_cast<Uint32>(target) - static_cast<Uint32>(TextureUploadTarget::CubeMapPositiveX);
}
static const MG_State::GLState::FramebufferAttachmentObject* GetClearableAttachment(
const MG_State::GLState::FramebufferObject& drawFbo, FramebufferAttachmentType attachmentType) { const MG_State::GLState::FramebufferObject& drawFbo, FramebufferAttachmentType attachmentType) {
if (attachmentType == FramebufferAttachmentType::None) { if (attachmentType == FramebufferAttachmentType::None) {
return nullptr; return nullptr;
@@ -23,7 +39,31 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return nullptr; return nullptr;
} }
return attachment.GetTexture(); return &attachment;
}
PendingClearKey VkClearManager::MakePendingClearKey(MG_State::GLState::ITextureObject* texture, Uint32 mipLevel,
Uint32 baseArrayLayer, Uint32 layerCount) {
return PendingClearKey {
.texture = texture,
.textureLifetimeId = texture ? texture->GetLifetimeId() : 0,
.mipLevel = mipLevel,
.baseArrayLayer = baseArrayLayer,
.layerCount = layerCount,
};
}
PendingClearKey VkClearManager::MakePendingClearKey(
const MG_State::GLState::FramebufferAttachmentObject& attachment) {
MOBILEGL_ASSERT(attachment.IsTexture() && !attachment.IsRenderbuffer(),
"MakePendingClearKey requires a texture framebuffer attachment");
auto* texture = attachment.GetTexture().get();
MOBILEGL_ASSERT(texture != nullptr, "MakePendingClearKey: texture attachment resolved to null");
const Uint32 mipLevel = static_cast<Uint32>(std::max(attachment.GetTextureLevel(), 0));
const TextureUploadTarget uploadTarget = attachment.GetTextureUploadTarget();
const Uint32 baseArrayLayer = ResolveAttachmentBaseArrayLayer(uploadTarget);
const Uint32 layerCount = IsCubeMapFaceUploadTarget(uploadTarget) ? 1u : 1u;
return MakePendingClearKey(texture, mipLevel, baseArrayLayer, layerCount);
} }
Bool VkClearManager::Initialize() { Bool VkClearManager::Initialize() {
@@ -31,7 +71,74 @@ namespace MobileGL::MG_Backend::DirectVulkan {
} }
void VkClearManager::Shutdown() { void VkClearManager::Shutdown() {
const std::lock_guard<std::mutex> lock(m_mutex);
m_pendingClears.clear();
m_aliveObjects.clear();
}
TextureIdentity VkClearManager::MakeTextureIdentity(MG_State::GLState::ITextureObject* texture) {
return TextureIdentity {
.texture = texture,
.lifetimeId = texture ? texture->GetLifetimeId() : 0,
};
}
void VkClearManager::MergeClearPayload(ClearAttachmentPayload& dst, const ClearAttachmentPayload& src) {
dst.mask |= src.mask;
if ((src.mask & GL_COLOR_BUFFER_BIT) != 0) {
dst.color = src.color;
}
if ((src.mask & GL_DEPTH_BUFFER_BIT) != 0) {
dst.depth = src.depth;
}
if ((src.mask & GL_STENCIL_BUFFER_BIT) != 0) {
dst.stencil = src.stencil;
}
}
void VkClearManager::ErasePendingClearsForTextureLocked(const TextureIdentity& identity) {
Vector<PendingClearKey> keysToErase;
keysToErase.reserve(m_pendingClears.size());
for (auto it = m_pendingClears.begin(); it != m_pendingClears.end(); ++it) {
if (PendingClearMatchesTextureIdentity(it->first, identity)) {
keysToErase.emplace_back(it->first);
}
}
for (const auto& key : keysToErase) {
m_pendingClears.erase(key);
}
m_aliveObjects.erase(identity);
}
Bool VkClearManager::LockTextureIdentityLocked(const TextureIdentity& identity,
SharedPtr<MG_State::GLState::ITextureObject>& outTexture) {
outTexture.reset();
if (identity.texture == nullptr) {
return false;
}
auto aliveIt = m_aliveObjects.find(identity);
if (aliveIt == m_aliveObjects.end()) {
ErasePendingClearsForTextureLocked(identity);
return false;
}
outTexture = aliveIt->second.lock();
if (!outTexture || outTexture.get() != identity.texture || outTexture->GetLifetimeId() != identity.lifetimeId) {
ErasePendingClearsForTextureLocked(identity);
outTexture.reset();
return false;
}
return true;
}
Bool VkClearManager::LockTextureLocked(const PendingClearKey& key,
SharedPtr<MG_State::GLState::ITextureObject>& outTexture) {
return LockTextureIdentityLocked(TextureIdentity{
.texture = key.texture,
.lifetimeId = key.textureLifetimeId,
}, outTexture);
} }
void VkClearManager::QueueClear(GLbitfield mask, const ClearFramebufferPayload& clearPayload, void VkClearManager::QueueClear(GLbitfield mask, const ClearFramebufferPayload& clearPayload,
@@ -40,88 +147,143 @@ namespace MobileGL::MG_Backend::DirectVulkan {
auto& drawbufs = drawFbo.GetDrawBuffers(); auto& drawbufs = drawFbo.GetDrawBuffers();
// This should automatically work on default & offscreen FBO // This should automatically work on default & offscreen FBO
for (auto drawbuf: drawbufs) { for (auto drawbuf: drawbufs) {
auto texture = GetClearableAttachmentTexture(drawFbo, drawbuf); const auto* attachment = GetClearableAttachment(drawFbo, drawbuf);
if (!texture) { if (!attachment) {
continue; continue;
} }
QueueClear({ QueueClear({
.mask = GL_COLOR_BUFFER_BIT, .mask = GL_COLOR_BUFFER_BIT,
.color = clearPayload.color .color = clearPayload.color
}, texture); }, *attachment);
MGLOG_D("%s: %s (texture %d) - color = (%.2f, %.2f, %.2f, %.2f)", __func__, MGLOG_D("%s: %s (texture %d) - color = (%.2f, %.2f, %.2f, %.2f)", __func__,
MG_Util::ConvertFramebufferAttachmentTypeToString(drawbuf).c_str(), MG_Util::ConvertFramebufferAttachmentTypeToString(drawbuf).c_str(),
texture->GetExternalIndex(), attachment->GetTexture()->GetExternalIndex(),
clearPayload.color[0], clearPayload.color[1], clearPayload.color[2], clearPayload.color[3]); clearPayload.color[0], clearPayload.color[1], clearPayload.color[2], clearPayload.color[3]);
} }
} }
if (mask & GL_DEPTH_BUFFER_BIT) { if (mask & GL_DEPTH_BUFFER_BIT) {
auto texture = GetClearableAttachmentTexture(drawFbo, FramebufferAttachmentType::Depth); const auto* attachment = GetClearableAttachment(drawFbo, FramebufferAttachmentType::Depth);
if (texture) { if (attachment) {
QueueClear({ QueueClear({
.mask = GL_DEPTH_BUFFER_BIT, .mask = GL_DEPTH_BUFFER_BIT,
.depth = clearPayload.depth, .depth = clearPayload.depth,
}, texture); }, *attachment);
MGLOG_D("%s: Depth (texture %d) - depth = (%.2f)", __func__, MGLOG_D("%s: Depth (texture %d) - depth = (%.2f)", __func__,
texture->GetExternalIndex(), clearPayload.depth); attachment->GetTexture()->GetExternalIndex(), clearPayload.depth);
} }
} }
if (mask & GL_STENCIL_BUFFER_BIT) { if (mask & GL_STENCIL_BUFFER_BIT) {
auto texture = GetClearableAttachmentTexture(drawFbo, FramebufferAttachmentType::Stencil); const auto* attachment = GetClearableAttachment(drawFbo, FramebufferAttachmentType::Stencil);
if (texture) { if (attachment) {
QueueClear({ QueueClear({
.mask = GL_STENCIL_BUFFER_BIT, .mask = GL_STENCIL_BUFFER_BIT,
.stencil = clearPayload.stencil, .stencil = clearPayload.stencil,
}, texture); }, *attachment);
MGLOG_D("%s: Stencil (texture %d) - stencil = (%u)", __func__, MGLOG_D("%s: Stencil (texture %d) - stencil = (%u)", __func__,
texture->GetExternalIndex(), clearPayload.stencil); attachment->GetTexture()->GetExternalIndex(), clearPayload.stencil);
} }
} }
} }
void VkClearManager::QueueClear(const ClearAttachmentPayload& clearPayload, void VkClearManager::QueueClear(const ClearAttachmentPayload& clearPayload,
const SharedPtr<MG_State::GLState::ITextureObject>& texture) { const SharedPtr<MG_State::GLState::ITextureObject>& texture) {
if (clearPayload.mask == 0) { if (clearPayload.mask == 0 || !texture) {
return; return;
} }
WeakPtr<MG_State::GLState::ITextureObject> weakTexturePtr = texture;
if (weakTexturePtr.expired()) const PendingClearKey key = MakePendingClearKey(texture.get());
const std::lock_guard<std::mutex> lock(m_mutex);
m_aliveObjects[MakeTextureIdentity(texture.get())] = texture;
auto& pending = m_pendingClears[key];
MergeClearPayload(pending, clearPayload);
}
void VkClearManager::QueueClear(const ClearAttachmentPayload& clearPayload,
const MG_State::GLState::FramebufferAttachmentObject& attachment) {
if (clearPayload.mask == 0 || !attachment.IsTexture() || attachment.IsRenderbuffer()) {
return; return;
auto* pTexture = weakTexturePtr.lock().get();
m_aliveObjects[pTexture] = weakTexturePtr;
auto& pending = m_pendingClears[pTexture];
pending.mask |= clearPayload.mask;
if (clearPayload.mask & GL_COLOR_BUFFER_BIT) {
pending.color = clearPayload.color;
} }
if (clearPayload.mask & GL_DEPTH_BUFFER_BIT) { const auto texture = attachment.GetTexture();
pending.depth = clearPayload.depth; if (!texture) {
} return;
if (clearPayload.mask & GL_STENCIL_BUFFER_BIT) {
pending.stencil = clearPayload.stencil;
} }
const PendingClearKey key = MakePendingClearKey(attachment);
const std::lock_guard<std::mutex> lock(m_mutex);
m_aliveObjects[MakeTextureIdentity(texture.get())] = texture;
auto& pending = m_pendingClears[key];
MergeClearPayload(pending, clearPayload);
} }
Bool VkClearManager::HasPendingClear(MG_State::GLState::ITextureObject* texture) { Bool VkClearManager::HasPendingClear(MG_State::GLState::ITextureObject* texture) {
return m_pendingClears.find(texture) != m_pendingClears.end(); if (texture == nullptr) {
}
Bool VkClearManager::GetPendingClear(MG_State::GLState::ITextureObject* texture, ClearAttachmentPayload& outPayload) {
if (m_aliveObjects.find(texture) == m_aliveObjects.end() ||
m_pendingClears.find(texture) == m_pendingClears.end()) {
MGLOG_D("%s: Failed getting pending clear for texture %d", __func__, texture->GetExternalIndex());
return false; return false;
} }
outPayload = m_pendingClears[texture]; const Uint64 lifetimeId = texture->GetLifetimeId();
MGLOG_D("%s: Got pending clear for texture %d (%s), mask=0x%x clear value: color = (%.2f, %.2f, %.2f, %.2f), depth = (%.2f), stencil = (%u)", __func__, const std::lock_guard<std::mutex> lock(m_mutex);
texture->GetExternalIndex(), for (auto it = m_pendingClears.begin(); it != m_pendingClears.end(); ++it) {
MG_Util::ConvertTextureInternalFormatToString(texture->GetFormat()).c_str(), if (it->first.texture == texture && it->first.textureLifetimeId == lifetimeId) {
SharedPtr<MG_State::GLState::ITextureObject> liveTexture;
return LockTextureLocked(it->first, liveTexture);
}
}
return false;
}
Bool VkClearManager::HasPendingClear(const PendingClearKey& key) {
if (key.texture == nullptr) {
return false;
}
const std::lock_guard<std::mutex> lock(m_mutex);
if (m_pendingClears.find(key) == m_pendingClears.end()) {
return false;
}
SharedPtr<MG_State::GLState::ITextureObject> liveTexture;
return LockTextureLocked(key, liveTexture);
}
Bool VkClearManager::HasPendingClear(const MG_State::GLState::FramebufferAttachmentObject& attachment) {
if (!attachment.IsTexture() || attachment.IsRenderbuffer() || !attachment.GetTexture()) {
return false;
}
return HasPendingClear(MakePendingClearKey(attachment));
}
Bool VkClearManager::GetPendingClear(const PendingClearKey& key, ClearAttachmentPayload& outPayload) {
SharedPtr<MG_State::GLState::ITextureObject> liveTexture;
return GetPendingClear(key, outPayload, liveTexture);
}
Bool VkClearManager::GetPendingClear(const PendingClearKey& key, ClearAttachmentPayload& outPayload,
SharedPtr<MG_State::GLState::ITextureObject>& outTexture) {
if (key.texture == nullptr) {
return false;
}
const std::lock_guard<std::mutex> lock(m_mutex);
if (!LockTextureLocked(key, outTexture)) {
return false;
}
auto it = m_pendingClears.find(key);
if (it == m_pendingClears.end()) {
outTexture.reset();
return false;
}
outPayload = it->second;
MGLOG_D("%s: Got pending clear for texture@%p lifetime=%llu, mip=%u layer=%u count=%u mask=0x%x clear value: color = (%.2f, %.2f, %.2f, %.2f), depth = (%.2f), stencil = (%u)", __func__,
static_cast<void*>(key.texture),
static_cast<unsigned long long>(key.textureLifetimeId),
key.mipLevel, key.baseArrayLayer, key.layerCount,
static_cast<Uint32>(outPayload.mask), static_cast<Uint32>(outPayload.mask),
outPayload.color[0], outPayload.color[1], outPayload.color[2], outPayload.color[3], outPayload.color[0], outPayload.color[1], outPayload.color[2], outPayload.color[3],
outPayload.depth, outPayload.depth,
@@ -129,27 +291,93 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return true; return true;
} }
Bool VkClearManager::GetPendingClear(const MG_State::GLState::FramebufferAttachmentObject& attachment,
ClearAttachmentPayload& outPayload) {
if (!attachment.IsTexture() || attachment.IsRenderbuffer() || !attachment.GetTexture()) {
MGLOG_D("%s: Failed getting pending clear for non-texture framebuffer attachment", __func__);
return false;
}
return GetPendingClear(MakePendingClearKey(attachment), outPayload);
}
Bool VkClearManager::GetPendingClears(MG_State::GLState::ITextureObject* texture,
Vector<PendingClearEntry>& outEntries) {
outEntries.clear();
if (texture == nullptr) {
return false;
}
const Uint64 lifetimeId = texture->GetLifetimeId();
const std::lock_guard<std::mutex> lock(m_mutex);
SharedPtr<MG_State::GLState::ITextureObject> liveTexture;
if (!LockTextureIdentityLocked(MakeTextureIdentity(texture), liveTexture)) {
return false;
}
for (auto it = m_pendingClears.begin(); it != m_pendingClears.end(); ++it) {
if (it->first.texture == texture && it->first.textureLifetimeId == lifetimeId) {
outEntries.emplace_back(PendingClearEntry{.key = it->first, .payload = it->second});
}
}
return !outEntries.empty();
}
void VkClearManager::PopPendingClear(MG_State::GLState::ITextureObject* texture) { void VkClearManager::PopPendingClear(MG_State::GLState::ITextureObject* texture) {
MGLOG_D("%s: Pop pending clear for texture %d", __func__, texture->GetExternalIndex()); if (texture == nullptr) {
m_aliveObjects.erase(texture); return;
m_pendingClears.erase(texture); }
const TextureIdentity identity = MakeTextureIdentity(texture);
MGLOG_D("%s: Pop all pending clears for texture %d", __func__, texture->GetExternalIndex());
const std::lock_guard<std::mutex> lock(m_mutex);
ErasePendingClearsForTextureLocked(identity);
}
void VkClearManager::PopPendingClear(const PendingClearKey& key) {
if (key.texture == nullptr) {
return;
}
{
const std::lock_guard<std::mutex> lock(m_mutex);
auto it = m_pendingClears.find(key);
if (it != m_pendingClears.end()) {
m_pendingClears.erase(it);
}
}
MGLOG_D("%s: Pop pending clear for texture@%p lifetime=%llu mip=%u layer=%u count=%u", __func__,
static_cast<void*>(key.texture), static_cast<unsigned long long>(key.textureLifetimeId),
key.mipLevel, key.baseArrayLayer, key.layerCount);
}
void VkClearManager::PopPendingClear(const MG_State::GLState::FramebufferAttachmentObject& attachment) {
if (!attachment.IsTexture() || attachment.IsRenderbuffer() || !attachment.GetTexture()) {
return;
}
PopPendingClear(MakePendingClearKey(attachment));
} }
SizeT VkClearManager::CollectGarbage() { SizeT VkClearManager::CollectGarbage() {
const std::lock_guard<std::mutex> lock(m_mutex);
m_gcCounter++; m_gcCounter++;
if (m_gcCounter != 0) { if (m_gcCounter != 0) {
return 0; return 0;
} }
SizeT count = 0; Vector<TextureIdentity> expiredTextures;
for (auto it = m_aliveObjects.begin(); it != m_aliveObjects.end();) { expiredTextures.reserve(m_aliveObjects.size());
auto current = it++; for (auto it = m_aliveObjects.begin(); it != m_aliveObjects.end(); ++it) {
if (current->second.expired()) { if (it->second.expired()) {
m_pendingClears.erase(current->first); expiredTextures.emplace_back(it->first);
m_aliveObjects.erase(current);
++count;
} }
} }
return count; if (expiredTextures.empty()) {
return 0;
}
for (const auto& identity : expiredTextures) {
ErasePendingClearsForTextureLocked(identity);
}
return expiredTextures.size();
} }
} // namespace MobileGL::MG_Backend::DirectVulkan } // namespace MobileGL::MG_Backend::DirectVulkan
@@ -14,6 +14,7 @@
#include "MG_Util/Math/VectorTypes.h" #include "MG_Util/Math/VectorTypes.h"
#include <Includes.h> #include <Includes.h>
#include <unordered_map>
namespace MobileGL::MG_Backend::DirectVulkan { namespace MobileGL::MG_Backend::DirectVulkan {
struct ClearFramebufferPayload { struct ClearFramebufferPayload {
@@ -29,8 +30,64 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Uint32 stencil = 0; Uint32 stencil = 0;
}; };
struct PendingClearKey {
MG_State::GLState::ITextureObject* texture = nullptr;
Uint64 textureLifetimeId = 0;
Uint32 mipLevel = 0;
Uint32 baseArrayLayer = 0;
Uint32 layerCount = 1;
Bool operator==(const PendingClearKey& other) const {
return texture == other.texture && textureLifetimeId == other.textureLifetimeId &&
mipLevel == other.mipLevel &&
baseArrayLayer == other.baseArrayLayer && layerCount == other.layerCount;
}
};
struct TextureIdentity {
MG_State::GLState::ITextureObject* texture = nullptr;
Uint64 lifetimeId = 0;
Bool operator==(const TextureIdentity& other) const {
return texture == other.texture && lifetimeId == other.lifetimeId;
}
};
struct PendingClearEntry {
PendingClearKey key{};
ClearAttachmentPayload payload{};
};
struct PendingClearKeyHash {
SizeT operator()(const PendingClearKey& key) const {
const SizeT textureHash = std::hash<MG_State::GLState::ITextureObject*>{}(key.texture);
const SizeT textureLifetimeHash = std::hash<Uint64>{}(key.textureLifetimeId);
const SizeT mipHash = std::hash<Uint32>{}(key.mipLevel);
const SizeT layerHash = std::hash<Uint32>{}(key.baseArrayLayer);
const SizeT layerCountHash = std::hash<Uint32>{}(key.layerCount);
SizeT hash = textureHash;
hash ^= textureLifetimeHash + 0x9e3779b9u + (hash << 6) + (hash >> 2);
hash ^= mipHash + 0x9e3779b9u + (hash << 6) + (hash >> 2);
hash ^= layerHash + 0x9e3779b9u + (hash << 6) + (hash >> 2);
hash ^= layerCountHash + 0x9e3779b9u + (hash << 6) + (hash >> 2);
return hash;
}
};
struct TextureIdentityHash {
SizeT operator()(const TextureIdentity& key) const {
SizeT hash = std::hash<MG_State::GLState::ITextureObject*>{}(key.texture);
hash ^= std::hash<Uint64>{}(key.lifetimeId) + 0x9e3779b9u + (hash << 6) + (hash >> 2);
return hash;
}
};
class VkClearManager { class VkClearManager {
public: public:
static PendingClearKey MakePendingClearKey(const MG_State::GLState::FramebufferAttachmentObject& attachment);
static PendingClearKey MakePendingClearKey(MG_State::GLState::ITextureObject* texture, Uint32 mipLevel = 0,
Uint32 baseArrayLayer = 0, Uint32 layerCount = 1);
Bool Initialize(); Bool Initialize();
void Shutdown(); void Shutdown();
@@ -38,13 +95,33 @@ namespace MobileGL::MG_Backend::DirectVulkan {
void QueueClear( void QueueClear(
const ClearAttachmentPayload& clearPayload, const ClearAttachmentPayload& clearPayload,
const SharedPtr<MG_State::GLState::ITextureObject>& texture); const SharedPtr<MG_State::GLState::ITextureObject>& texture);
void QueueClear(const ClearAttachmentPayload& clearPayload,
const MG_State::GLState::FramebufferAttachmentObject& attachment);
Bool HasPendingClear(MG_State::GLState::ITextureObject* texture); Bool HasPendingClear(MG_State::GLState::ITextureObject* texture);
Bool GetPendingClear(MG_State::GLState::ITextureObject* texture, ClearAttachmentPayload& outPayload); Bool HasPendingClear(const PendingClearKey& key);
Bool HasPendingClear(const MG_State::GLState::FramebufferAttachmentObject& attachment);
Bool GetPendingClear(const PendingClearKey& key, ClearAttachmentPayload& outPayload);
Bool GetPendingClear(const PendingClearKey& key, ClearAttachmentPayload& outPayload,
SharedPtr<MG_State::GLState::ITextureObject>& outTexture);
Bool GetPendingClear(const MG_State::GLState::FramebufferAttachmentObject& attachment,
ClearAttachmentPayload& outPayload);
Bool GetPendingClears(MG_State::GLState::ITextureObject* texture, Vector<PendingClearEntry>& outEntries);
void PopPendingClear(MG_State::GLState::ITextureObject* texture); void PopPendingClear(MG_State::GLState::ITextureObject* texture);
void PopPendingClear(const PendingClearKey& key);
void PopPendingClear(const MG_State::GLState::FramebufferAttachmentObject& attachment);
SizeT CollectGarbage(); SizeT CollectGarbage();
private: private:
static TextureIdentity MakeTextureIdentity(MG_State::GLState::ITextureObject* texture);
static void MergeClearPayload(ClearAttachmentPayload& dst, const ClearAttachmentPayload& src);
void ErasePendingClearsForTextureLocked(const TextureIdentity& identity);
Bool LockTextureIdentityLocked(const TextureIdentity& identity,
SharedPtr<MG_State::GLState::ITextureObject>& outTexture);
Bool LockTextureLocked(const PendingClearKey& key,
SharedPtr<MG_State::GLState::ITextureObject>& outTexture);
Uint8 m_gcCounter = 0; Uint8 m_gcCounter = 0;
UnorderedMap<MG_State::GLState::ITextureObject*, ClearAttachmentPayload> m_pendingClears; mutable std::mutex m_mutex;
UnorderedMap<MG_State::GLState::ITextureObject*, WeakPtr<MG_State::GLState::ITextureObject>> m_aliveObjects; std::unordered_map<PendingClearKey, ClearAttachmentPayload, PendingClearKeyHash> m_pendingClears;
std::unordered_map<TextureIdentity, WeakPtr<MG_State::GLState::ITextureObject>, TextureIdentityHash> m_aliveObjects;
}; };
} // namespace MobileGL::MG_Backend::DirectVulkan } // namespace MobileGL::MG_Backend::DirectVulkan
@@ -22,6 +22,32 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return requestedAlpha; return requestedAlpha;
} }
static Bool IsCubeMapFaceUploadTarget(TextureUploadTarget target) {
return target >= TextureUploadTarget::CubeMapPositiveX &&
target <= TextureUploadTarget::CubeMapNegativeZ;
}
static Uint32 ResolveAttachmentBaseArrayLayer(const MG_State::GLState::FramebufferAttachmentObject& attachment) {
const TextureUploadTarget uploadTarget = attachment.GetTextureUploadTarget();
if (!IsCubeMapFaceUploadTarget(uploadTarget)) {
return 0;
}
return static_cast<Uint32>(uploadTarget) - static_cast<Uint32>(TextureUploadTarget::CubeMapPositiveX);
}
static Uint32 ResolveAttachmentLayerCount(const MG_State::GLState::FramebufferAttachmentObject& attachment) {
static_cast<void>(attachment);
return 1u;
}
static VkImageViewType ResolveAttachmentViewType(
const MG_State::GLState::FramebufferAttachmentObject& attachment,
const VkTextureManager::TextureResource& resource) {
return IsCubeMapFaceUploadTarget(attachment.GetTextureUploadTarget()) ?
VK_IMAGE_VIEW_TYPE_2D :
resource.viewType;
}
static MG_State::GLState::ITextureObject* ResolveCompleteColorAttachmentTexture( static MG_State::GLState::ITextureObject* ResolveCompleteColorAttachmentTexture(
const MG_State::GLState::FramebufferObject& fbo, const MG_State::GLState::FramebufferObject& fbo,
FramebufferAttachmentType attachmentType, FramebufferAttachmentType attachmentType,
@@ -78,6 +104,14 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return info; return info;
} }
IntVec2 ResolveRenderPassFramebufferExtent(Bool isDefaultFbo, const TextureSize& attachmentExtent,
VkExtent2D swapchainExtent) {
if (isDefaultFbo) {
return {static_cast<Int>(swapchainExtent.width), static_cast<Int>(swapchainExtent.height)};
}
return {attachmentExtent.x(), attachmentExtent.y()};
}
VkRenderPassManager::VkRenderPassManager(VkDevice device, VkRenderPassManager::VkRenderPassManager(VkDevice device,
const VulkanRendererConfig& config, VkClearManager& clearManager, VkTextureManager& textureManager, const VulkanRendererConfig& config, VkClearManager& clearManager, VkTextureManager& textureManager,
SwapchainObject& swapchainObject): SwapchainObject& swapchainObject):
@@ -96,12 +130,16 @@ namespace MobileGL::MG_Backend::DirectVulkan {
} }
void VkRenderPassManager::Shutdown() { void VkRenderPassManager::Shutdown() {
m_renderPasses.clear();
RenderPassEntry::s_textureResourcesScratch.clear();
s_activeRenderPass = {};
s_hasActiveRenderPass = false;
} }
VkRenderPassManager::HashType VkRenderPassManager::ComputeHash( VkRenderPassManager::HashType VkRenderPassManager::ComputeHash(
const MG_State::GLState::FramebufferObject& fbo, Uint32 swapchainImageIndex, Bool includePendingClear) const { const MG_State::GLState::FramebufferObject& fbo, Uint32 swapchainImageIndex, Bool includePendingClear) const {
XXHASH_VERIFY(XXH64_reset(m_hashState, m_config.CacheVersion)); XXHASH_VERIFY(XXH64_reset(m_hashState, m_config.CacheVersion));
const Bool isDefaultFbo = (&fbo == MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo->defaultFBO.get()); const Bool isDefaultFbo = fbo.IsDefaultFramebuffer();
if (isDefaultFbo) { if (isDefaultFbo) {
XXHASH_VERIFY(XXH64_update(m_hashState, &swapchainImageIndex, sizeof(swapchainImageIndex))); XXHASH_VERIFY(XXH64_update(m_hashState, &swapchainImageIndex, sizeof(swapchainImageIndex)));
} }
@@ -132,25 +170,34 @@ namespace MobileGL::MG_Backend::DirectVulkan {
contentPtr = att.GetRenderbuffer().get(); contentPtr = att.GetRenderbuffer().get();
XXHASH_VERIFY(XXH64_update(m_hashState, &contentPtr, sizeof(contentPtr))); XXHASH_VERIFY(XXH64_update(m_hashState, &contentPtr, sizeof(contentPtr)));
if (att.IsTexture()) { if (att.IsTexture()) {
const Uint64 textureLifetimeId = att.GetTexture()->GetLifetimeId();
XXHASH_VERIFY(XXH64_update(m_hashState, &textureLifetimeId, sizeof(textureLifetimeId)));
const Int textureLevel = att.GetTextureLevel(); const Int textureLevel = att.GetTextureLevel();
XXHASH_VERIFY(XXH64_update(m_hashState, &textureLevel, sizeof(textureLevel))); XXHASH_VERIFY(XXH64_update(m_hashState, &textureLevel, sizeof(textureLevel)));
const TextureUploadTarget textureUploadTarget = att.GetTextureUploadTarget();
XXHASH_VERIFY(XXH64_update(m_hashState, &textureUploadTarget, sizeof(textureUploadTarget)));
Uint64 imageIdentity = 0; Uint64 imageIdentity = 0;
auto* texture = att.GetTexture().get(); auto* texture = att.GetTexture().get();
auto* resource = m_textureManager.SyncTextureAndGetDescriptor(*texture); auto* resource = m_textureManager.SyncTextureAndGetDescriptor(*texture);
if (resource != nullptr) { if (resource != nullptr) {
imageIdentity = reinterpret_cast<Uint64>(resource->image); imageIdentity = reinterpret_cast<Uint64>(resource->image);
XXHASH_VERIFY(XXH64_update(m_hashState, &resource->sampleCount, sizeof(resource->sampleCount)));
} else {
const VkSampleCountFlagBits fallbackSampleCount = VK_SAMPLE_COUNT_1_BIT;
XXHASH_VERIFY(XXH64_update(m_hashState, &fallbackSampleCount, sizeof(fallbackSampleCount)));
} }
XXHASH_VERIFY(XXH64_update(m_hashState, &imageIdentity, sizeof(imageIdentity))); XXHASH_VERIFY(XXH64_update(m_hashState, &imageIdentity, sizeof(imageIdentity)));
} }
if (includePendingClear && att.IsTexture()) { if (includePendingClear && att.IsTexture()) {
auto* texture = att.GetTexture().get(); auto* texture = att.GetTexture().get();
auto hasClear = m_clearManager.HasPendingClear(texture); const auto pendingClearKey = VkClearManager::MakePendingClearKey(att);
auto hasClear = m_clearManager.HasPendingClear(pendingClearKey);
XXHASH_VERIFY(XXH64_update(m_hashState, &hasClear, sizeof(hasClear))); XXHASH_VERIFY(XXH64_update(m_hashState, &hasClear, sizeof(hasClear)));
if (hasClear) { if (hasClear) {
ClearAttachmentPayload clearPayload{}; ClearAttachmentPayload clearPayload{};
Bool hasPayload = m_clearManager.GetPendingClear(texture, clearPayload); Bool hasPayload = m_clearManager.GetPendingClear(pendingClearKey, clearPayload);
XXHASH_VERIFY(XXH64_update(m_hashState, &hasPayload, sizeof(hasPayload))); XXHASH_VERIFY(XXH64_update(m_hashState, &hasPayload, sizeof(hasPayload)));
if (hasPayload) { if (hasPayload) {
XXHASH_VERIFY(XXH64_update(m_hashState, &clearPayload.mask, sizeof(clearPayload.mask))); XXHASH_VERIFY(XXH64_update(m_hashState, &clearPayload.mask, sizeof(clearPayload.mask)));
@@ -159,8 +206,11 @@ namespace MobileGL::MG_Backend::DirectVulkan {
VkImageLayout currentLayout = VK_IMAGE_LAYOUT_UNDEFINED; VkImageLayout currentLayout = VK_IMAGE_LAYOUT_UNDEFINED;
if (isDefaultFbo) { if (isDefaultFbo) {
if (attachment >= FramebufferAttachmentType::Color0 && const Bool isDefaultColorAttachment =
attachment <= FramebufferAttachmentType::Color31) { attachment == FramebufferAttachmentType::Color0 ||
(attachment >= FramebufferAttachmentType::FrontLeft &&
attachment <= FramebufferAttachmentType::BackRight);
if (isDefaultColorAttachment) {
currentLayout = m_swapchainObject.GetImageLayout(swapchainImageIndex); currentLayout = m_swapchainObject.GetImageLayout(swapchainImageIndex);
} else if (attachment == FramebufferAttachmentType::Depth || } else if (attachment == FramebufferAttachmentType::Depth ||
attachment == FramebufferAttachmentType::Stencil) { attachment == FramebufferAttachmentType::Stencil) {
@@ -197,18 +247,18 @@ namespace MobileGL::MG_Backend::DirectVulkan {
} }
const auto& att = fbo.GetAttachment(attachment); const auto& att = fbo.GetAttachment(attachment);
if (att.IsTexture() && m_clearManager.HasPendingClear(att.GetTexture().get())) { if (att.IsTexture() && m_clearManager.HasPendingClear(att)) {
return true; return true;
} }
} }
const auto& depthAtt = fbo.GetAttachment(FramebufferAttachmentType::Depth); const auto& depthAtt = fbo.GetAttachment(FramebufferAttachmentType::Depth);
if (depthAtt.IsTexture() && m_clearManager.HasPendingClear(depthAtt.GetTexture().get())) { if (depthAtt.IsTexture() && m_clearManager.HasPendingClear(depthAtt)) {
return true; return true;
} }
const auto& stencilAtt = fbo.GetAttachment(FramebufferAttachmentType::Stencil); const auto& stencilAtt = fbo.GetAttachment(FramebufferAttachmentType::Stencil);
if (stencilAtt.IsTexture() && m_clearManager.HasPendingClear(stencilAtt.GetTexture().get())) { if (stencilAtt.IsTexture() && m_clearManager.HasPendingClear(stencilAtt)) {
return true; return true;
} }
@@ -232,13 +282,17 @@ namespace MobileGL::MG_Backend::DirectVulkan {
if (it != m_renderPasses.end()) if (it != m_renderPasses.end())
return it->second; return it->second;
Bool isDefaultFbo = (&fbo == MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo->defaultFBO.get()); Bool isDefaultFbo = fbo.IsDefaultFramebuffer();
// Color attachment // Color attachment
auto& drawbufs = fbo.GetDrawBuffers(); auto& drawbufs = fbo.GetDrawBuffers();
const Uint32 colorAttachmentSlotCount = static_cast<Uint32>(drawbufs.size()); const Uint32 colorAttachmentSlotCount = static_cast<Uint32>(drawbufs.size());
Int width = 0; const VkExtent2D swapchainExtent = m_swapchainObject.GetExtent();
Int height = 0; // Default framebuffer attachments are frontend placeholders; Vulkan framebuffer extent must match the swapchain.
const IntVec2 defaultFramebufferExtent =
ResolveRenderPassFramebufferExtent(isDefaultFbo, {0, 0, 0}, swapchainExtent);
Int width = defaultFramebufferExtent.x();
Int height = defaultFramebufferExtent.y();
Vector<VkAttachmentDescription> attachmentDescriptions; Vector<VkAttachmentDescription> attachmentDescriptions;
attachmentDescriptions.reserve(colorAttachmentSlotCount + 1); attachmentDescriptions.reserve(colorAttachmentSlotCount + 1);
// Keep the full GL draw buffer slot span so fragment outputs targeting GL_NONE map to VK_ATTACHMENT_UNUSED. // Keep the full GL draw buffer slot span so fragment outputs targeting GL_NONE map to VK_ATTACHMENT_UNUSED.
@@ -256,6 +310,21 @@ namespace MobileGL::MG_Backend::DirectVulkan {
textureResources.reserve(colorAttachmentSlotCount + 1); textureResources.reserve(colorAttachmentSlotCount + 1);
Vector<VkImageView> attachmentViews; Vector<VkImageView> attachmentViews;
attachmentViews.reserve(colorAttachmentSlotCount + 1); attachmentViews.reserve(colorAttachmentSlotCount + 1);
VkSampleCountFlagBits renderPassSampleCount = VK_SAMPLE_COUNT_1_BIT;
Bool hasRenderPassSampleCount = false;
const auto adoptRenderPassSampleCount = [&](VkSampleCountFlagBits sampleCount,
const char* attachmentKind,
Int attachmentId) {
if (!hasRenderPassSampleCount) {
renderPassSampleCount = sampleCount;
hasRenderPassSampleCount = true;
return;
}
MOBILEGL_ASSERT(renderPassSampleCount == sampleCount,
"GetOrCreateRenderPass: mismatched sample count %d on %s attachment %d (expected %d)",
static_cast<Int>(sampleCount), attachmentKind, attachmentId,
static_cast<Int>(renderPassSampleCount));
};
// This should automatically work on default & offscreen FBO // This should automatically work on default & offscreen FBO
// assuming default FBO has the right param // assuming default FBO has the right param
for (Uint32 i = 0; i < colorAttachmentSlotCount; ++i) { for (Uint32 i = 0; i < colorAttachmentSlotCount; ++i) {
@@ -273,17 +342,16 @@ namespace MobileGL::MG_Backend::DirectVulkan {
// Color attachment description // Color attachment description
VkAttachmentDescription& desc = attachmentDescriptions.back(); VkAttachmentDescription& desc = attachmentDescriptions.back();
switch (textureTarget) { switch (textureTarget) {
case TextureTarget::Texture2D: { case TextureTarget::Texture2D:
auto* texture2d = case TextureTarget::Texture2DMultisample: {
static_cast<MG_State::GLState::TextureObject2D*>(texture);
desc.flags = 0; desc.flags = 0;
desc.format = isDefaultFbo ? desc.format = isDefaultFbo ?
m_swapchainObject.GetSurfaceFormat().format : m_swapchainObject.GetSurfaceFormat().format :
MG_Util::ConvertTextureInternalFormatToVkEnum( MG_Util::ConvertTextureInternalFormatToVkEnum(
texture2d->GetFormat()); texture->GetFormat());
desc.samples = VK_SAMPLE_COUNT_1_BIT; VkSampleCountFlagBits attachmentSampleCount = VK_SAMPLE_COUNT_1_BIT;
ClearAttachmentPayload clearPayload{}; ClearAttachmentPayload clearPayload{};
Bool hasClear = m_clearManager.GetPendingClear(texture, clearPayload); Bool hasClear = m_clearManager.GetPendingClear(att, clearPayload);
VkImageLayout trackedColorLayout = VK_IMAGE_LAYOUT_UNDEFINED; VkImageLayout trackedColorLayout = VK_IMAGE_LAYOUT_UNDEFINED;
desc.loadOp = hasClear ? desc.loadOp = hasClear ?
VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_CLEAR :
@@ -297,13 +365,15 @@ namespace MobileGL::MG_Backend::DirectVulkan {
if (hasClear) { if (hasClear) {
pendingClearAttachments.emplace_back(PendingClearAttachmentInfo { pendingClearAttachments.emplace_back(PendingClearAttachmentInfo {
.attachmentIndex = attachmentIndex, .attachmentIndex = attachmentIndex,
.texture = texture .key = VkClearManager::MakePendingClearKey(att)
}); });
} }
const IntVec2 attachmentExtent =
ResolveRenderPassFramebufferExtent(isDefaultFbo, att.GetSize(), swapchainExtent);
if (width == 0) if (width == 0)
width = att.GetSize().x(); width = attachmentExtent.x();
if (height == 0) if (height == 0)
height = att.GetSize().y(); height = attachmentExtent.y();
if (isDefaultFbo) { if (isDefaultFbo) {
const auto& swapchainViews = m_swapchainObject.GetImageViews(); const auto& swapchainViews = m_swapchainObject.GetImageViews();
@@ -315,6 +385,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
.swapchainImageIndex = swapchainImageIndex, .swapchainImageIndex = swapchainImageIndex,
.finalLayout = desc.finalLayout, .finalLayout = desc.finalLayout,
}); });
attachmentSampleCount = VK_SAMPLE_COUNT_1_BIT;
textureResources.emplace_back(nullptr); textureResources.emplace_back(nullptr);
attachmentViews.emplace_back(swapchainViews[swapchainImageIndex]); attachmentViews.emplace_back(swapchainViews[swapchainImageIndex]);
} else { } else {
@@ -323,17 +394,25 @@ namespace MobileGL::MG_Backend::DirectVulkan {
"GetOrCreateRenderPass: SyncTextureAndGetDescriptor failed at color attachment %d", i); "GetOrCreateRenderPass: SyncTextureAndGetDescriptor failed at color attachment %d", i);
textureResources.emplace_back(textureResource); textureResources.emplace_back(textureResource);
desc.format = textureResource->format; desc.format = textureResource->format;
attachmentSampleCount = textureResource->sampleCount;
trackedColorLayout = textureResource->layout; trackedColorLayout = textureResource->layout;
trackedAttachmentLayouts.emplace_back(TrackedAttachmentLayoutInfo { trackedAttachmentLayouts.emplace_back(TrackedAttachmentLayoutInfo {
.target = TrackedAttachmentTarget::Texture, .target = TrackedAttachmentTarget::Texture,
.texture = texture, .texture = att.GetTexture(),
.textureMipLevel = attachmentMipLevel, .textureMipLevel = attachmentMipLevel,
.finalLayout = desc.finalLayout, .finalLayout = desc.finalLayout,
}); });
attachmentViews.emplace_back(m_textureManager.GetOrCreateViewAtMipLevel(*texture, attachmentMipLevel)); const Uint32 baseArrayLayer = ResolveAttachmentBaseArrayLayer(att);
const Uint32 layerCount = ResolveAttachmentLayerCount(att);
const VkImageViewType attachmentViewType = ResolveAttachmentViewType(att, *textureResource);
attachmentViews.emplace_back(
m_textureManager.GetOrCreateAttachmentViewAtMipLevel(
*texture, attachmentMipLevel, baseArrayLayer, layerCount, attachmentViewType));
MOBILEGL_ASSERT(attachmentViews.back() != VK_NULL_HANDLE, MOBILEGL_ASSERT(attachmentViews.back() != VK_NULL_HANDLE,
"GetOrCreateRenderPass: GetOrCreateAttachmentView failed at color attachment %d", i); "GetOrCreateRenderPass: GetOrCreateAttachmentView failed at color attachment %d", i);
} }
desc.samples = attachmentSampleCount;
adoptRenderPassSampleCount(attachmentSampleCount, "color", texture->GetExternalIndex());
if (!hasClear && trackedColorLayout == VK_IMAGE_LAYOUT_UNDEFINED) { if (!hasClear && trackedColorLayout == VK_IMAGE_LAYOUT_UNDEFINED) {
MGLOG_W("GetOrCreateRenderPass: color attachment textureId=%d starts with undefined layout and no clear; " MGLOG_W("GetOrCreateRenderPass: color attachment textureId=%d starts with undefined layout and no clear; "
@@ -357,19 +436,35 @@ namespace MobileGL::MG_Backend::DirectVulkan {
attachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; attachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
} }
// Depth attachment description // Depth/stencil attachment description
auto& depthAtt = fbo.GetAttachment(FramebufferAttachmentType::Depth); auto& depthAtt = fbo.GetAttachment(FramebufferAttachmentType::Depth);
auto& stencilAtt = fbo.GetAttachment(FramebufferAttachmentType::Stencil);
VkAttachmentDescription depthAttachmentDescription; VkAttachmentDescription depthAttachmentDescription;
VkAttachmentReference depthAttachmentRef; VkAttachmentReference depthAttachmentRef;
depthAttachmentRef.attachment = VK_ATTACHMENT_UNUSED; depthAttachmentRef.attachment = VK_ATTACHMENT_UNUSED;
depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
VkTextureManager::TextureResource* depthTextureResource = nullptr; VkTextureManager::TextureResource* depthTextureResource = nullptr;
if (depthAtt.IsComplete() && depthAtt.IsTexture()) { const auto isUsableDepthStencilAttachment = [](const auto& attachment) {
auto& texture = *depthAtt.GetTexture(); return attachment.IsComplete() && attachment.IsTexture();
const Uint32 attachmentMipLevel = static_cast<Uint32>(std::max(depthAtt.GetTextureLevel(), 0)); };
const auto* selectedDepthStencilAttachment = isUsableDepthStencilAttachment(depthAtt) ? &depthAtt :
(isUsableDepthStencilAttachment(stencilAtt) ? &stencilAtt : nullptr);
const Bool hasDistinctDepthAndStencilAttachments =
isUsableDepthStencilAttachment(depthAtt) && isUsableDepthStencilAttachment(stencilAtt) &&
(depthAtt.GetTexture().get() != stencilAtt.GetTexture().get() ||
depthAtt.GetTextureUploadTarget() != stencilAtt.GetTextureUploadTarget() ||
depthAtt.GetTextureLevel() != stencilAtt.GetTextureLevel());
if (hasDistinctDepthAndStencilAttachments) {
MGLOG_E("GetOrCreateRenderPass: separate depth/stencil attachments are not supported yet; using the depth attachment and ignoring the standalone stencil attachment for framebuffer %u",
fbo.GetExternalIndex());
}
if (selectedDepthStencilAttachment != nullptr) {
auto& texture = *selectedDepthStencilAttachment->GetTexture();
const Uint32 attachmentMipLevel =
static_cast<Uint32>(std::max(selectedDepthStencilAttachment->GetTextureLevel(), 0));
const Uint32 depthAttachmentIndex = static_cast<Uint32>(attachmentDescriptions.size()); const Uint32 depthAttachmentIndex = static_cast<Uint32>(attachmentDescriptions.size());
ClearAttachmentPayload clearPayload{}; ClearAttachmentPayload clearPayload{};
Bool hasClear = m_clearManager.GetPendingClear(&texture, clearPayload); Bool hasClear = m_clearManager.GetPendingClear(*selectedDepthStencilAttachment, clearPayload);
Bool clearDepth = hasClear && (clearPayload.mask & GL_DEPTH_BUFFER_BIT) != 0; Bool clearDepth = hasClear && (clearPayload.mask & GL_DEPTH_BUFFER_BIT) != 0;
Bool clearStencil = hasClear && (clearPayload.mask & GL_STENCIL_BUFFER_BIT) != 0; Bool clearStencil = hasClear && (clearPayload.mask & GL_STENCIL_BUFFER_BIT) != 0;
VkImageLayout trackedDepthLayout = isDefaultFbo ? VkImageLayout trackedDepthLayout = isDefaultFbo ?
@@ -385,10 +480,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
depthAttachmentDescription.format = isDefaultFbo ? depthAttachmentDescription.format = isDefaultFbo ?
m_swapchainObject.GetDepthStencilFormat() : m_swapchainObject.GetDepthStencilFormat() :
MG_Util::ConvertTextureInternalFormatToVkEnum(texture.GetFormat()); MG_Util::ConvertTextureInternalFormatToVkEnum(texture.GetFormat());
VkSampleCountFlagBits depthAttachmentSampleCount = VK_SAMPLE_COUNT_1_BIT;
if (!isDefaultFbo) { if (!isDefaultFbo) {
depthAttachmentDescription.format = depthTextureResource->format; depthAttachmentDescription.format = depthTextureResource->format;
depthAttachmentSampleCount = depthTextureResource->sampleCount;
} }
depthAttachmentDescription.samples = VK_SAMPLE_COUNT_1_BIT; depthAttachmentDescription.samples = depthAttachmentSampleCount;
adoptRenderPassSampleCount(depthAttachmentSampleCount, "depth/stencil", texture.GetExternalIndex());
const auto loadInfo = const auto loadInfo =
ResolveDepthStencilAttachmentLoadInfo(trackedDepthLayout, clearDepth, clearStencil); ResolveDepthStencilAttachmentLoadInfo(trackedDepthLayout, clearDepth, clearStencil);
depthAttachmentDescription.loadOp = loadInfo.depthLoadOp; depthAttachmentDescription.loadOp = loadInfo.depthLoadOp;
@@ -405,7 +503,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
if (hasClear) { if (hasClear) {
pendingClearAttachments.emplace_back(PendingClearAttachmentInfo { pendingClearAttachments.emplace_back(PendingClearAttachmentInfo {
.attachmentIndex = depthAttachmentIndex, .attachmentIndex = depthAttachmentIndex,
.texture = &texture .key = VkClearManager::MakePendingClearKey(*selectedDepthStencilAttachment)
}); });
} }
if (isDefaultFbo) { if (isDefaultFbo) {
@@ -426,17 +524,26 @@ namespace MobileGL::MG_Backend::DirectVulkan {
texture.GetExternalIndex()); texture.GetExternalIndex());
trackedAttachmentLayouts.emplace_back(TrackedAttachmentLayoutInfo { trackedAttachmentLayouts.emplace_back(TrackedAttachmentLayoutInfo {
.target = TrackedAttachmentTarget::Texture, .target = TrackedAttachmentTarget::Texture,
.texture = &texture, .texture = selectedDepthStencilAttachment->GetTexture(),
.textureMipLevel = attachmentMipLevel, .textureMipLevel = attachmentMipLevel,
.finalLayout = depthAttachmentDescription.finalLayout, .finalLayout = depthAttachmentDescription.finalLayout,
}); });
textureResources.emplace_back(depthTextureResource); textureResources.emplace_back(depthTextureResource);
attachmentViews.emplace_back(m_textureManager.GetOrCreateViewAtMipLevel(texture, attachmentMipLevel)); const Uint32 baseArrayLayer = ResolveAttachmentBaseArrayLayer(*selectedDepthStencilAttachment);
const Uint32 layerCount = ResolveAttachmentLayerCount(*selectedDepthStencilAttachment);
const VkImageViewType attachmentViewType =
ResolveAttachmentViewType(*selectedDepthStencilAttachment, *depthTextureResource);
attachmentViews.emplace_back(
m_textureManager.GetOrCreateAttachmentViewAtMipLevel(
texture, attachmentMipLevel, baseArrayLayer, layerCount, attachmentViewType));
MOBILEGL_ASSERT(attachmentViews.back() != VK_NULL_HANDLE, MOBILEGL_ASSERT(attachmentViews.back() != VK_NULL_HANDLE,
"GetOrCreateRenderPass: GetOrCreateAttachmentView failed at depth attachment"); "GetOrCreateRenderPass: GetOrCreateAttachmentView failed at depth attachment");
const IntVec2 attachmentExtent =
ResolveRenderPassFramebufferExtent(isDefaultFbo, selectedDepthStencilAttachment->GetSize(),
swapchainExtent);
if (width == 0 || height == 0) { if (width == 0 || height == 0) {
width = depthAtt.GetSize().x(); width = attachmentExtent.x();
height = depthAtt.GetSize().y(); height = attachmentExtent.y();
} }
} }
attachmentDescriptions.emplace_back(depthAttachmentDescription); attachmentDescriptions.emplace_back(depthAttachmentDescription);
@@ -453,7 +560,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
subpassDesc.colorAttachmentCount = colorAttachmentRefs.size(); subpassDesc.colorAttachmentCount = colorAttachmentRefs.size();
subpassDesc.pColorAttachments = colorAttachmentRefs.data(); subpassDesc.pColorAttachments = colorAttachmentRefs.data();
subpassDesc.pResolveAttachments = nullptr; subpassDesc.pResolveAttachments = nullptr;
subpassDesc.pDepthStencilAttachment = depthAtt.IsComplete() ? &depthAttachmentRef : VK_NULL_HANDLE; subpassDesc.pDepthStencilAttachment = hasDepthStencilAttachment ? &depthAttachmentRef : VK_NULL_HANDLE;
subpassDesc.preserveAttachmentCount = 0; subpassDesc.preserveAttachmentCount = 0;
subpassDesc.pPreserveAttachments = nullptr; subpassDesc.pPreserveAttachments = nullptr;
@@ -496,13 +603,15 @@ namespace MobileGL::MG_Backend::DirectVulkan {
static_cast<Uint32>(attachmentViews.size()), static_cast<Uint32>(attachmentViews.size()),
static_cast<Uint32>(colorAttachmentRefs.size()), static_cast<Uint32>(colorAttachmentRefs.size()),
hasDepthStencilAttachment, hasDepthStencilAttachment,
renderPassSampleCount,
extent, extent,
1 }; 1 };
MGLOG_D("VkRenderPassManager::GetOrCreateRenderPass: hash=0x%llx compatibilityHash=0x%llx attachmentCount=%u colorAttachmentCount=%u extent=%dx%d", MGLOG_D("VkRenderPassManager::GetOrCreateRenderPass: hash=0x%llx compatibilityHash=0x%llx attachmentCount=%u colorAttachmentCount=%u samples=%d extent=%dx%d",
static_cast<unsigned long long>(hash), static_cast<unsigned long long>(hash),
static_cast<unsigned long long>(compatibilityHash), static_cast<unsigned long long>(compatibilityHash),
renderPassEntry.attachmentCount, renderPassEntry.attachmentCount,
renderPassEntry.colorAttachmentCount, renderPassEntry.colorAttachmentCount,
static_cast<Int>(renderPassEntry.sampleCount),
extent.x(), extent.x(),
extent.y()); extent.y());
auto [insertedIt, _] = m_renderPasses.emplace(hash, Move(renderPassEntry)); auto [insertedIt, _] = m_renderPasses.emplace(hash, Move(renderPassEntry));
@@ -526,11 +635,12 @@ namespace MobileGL::MG_Backend::DirectVulkan {
clearValue.depthStencil = {1.0f, 0}; clearValue.depthStencil = {1.0f, 0};
} }
for (const auto& pending: renderPassEntry.pendingClearAttachments) { for (const auto& pending: renderPassEntry.pendingClearAttachments) {
if (!pending.texture || pending.attachmentIndex >= clearValues.size()) { if (pending.key.texture == nullptr || pending.attachmentIndex >= clearValues.size()) {
continue; continue;
} }
ClearAttachmentPayload clearPayload{}; ClearAttachmentPayload clearPayload{};
if (!s_clearManager->GetPendingClear(pending.texture, clearPayload)) { SharedPtr<MG_State::GLState::ITextureObject> liveTexture;
if (!s_clearManager->GetPendingClear(pending.key, clearPayload, liveTexture)) {
continue; continue;
} }
if ((clearPayload.mask & GL_COLOR_BUFFER_BIT) != 0) { if ((clearPayload.mask & GL_COLOR_BUFFER_BIT) != 0) {
@@ -538,7 +648,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
clearPayload.color.x(), clearPayload.color.x(),
clearPayload.color.y(), clearPayload.color.y(),
clearPayload.color.z(), clearPayload.color.z(),
ResolveColorClearAlpha(pending.texture, clearPayload.color.w()) ResolveColorClearAlpha(liveTexture.get(), clearPayload.color.w())
}; };
} }
if ((clearPayload.mask & GL_DEPTH_BUFFER_BIT) != 0) { if ((clearPayload.mask & GL_DEPTH_BUFFER_BIT) != 0) {
@@ -554,7 +664,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
for (const auto& pending: renderPassEntry.pendingClearAttachments) { for (const auto& pending: renderPassEntry.pendingClearAttachments) {
s_clearManager->PopPendingClear(pending.texture); s_clearManager->PopPendingClear(pending.key);
} }
s_activeRenderPass.hash = renderPassEntry.hash; s_activeRenderPass.hash = renderPassEntry.hash;
s_activeRenderPass.compatibilityHash = renderPassEntry.compatibilityHash; s_activeRenderPass.compatibilityHash = renderPassEntry.compatibilityHash;
@@ -573,11 +683,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
switch (trackedAttachment.target) { switch (trackedAttachment.target) {
case TrackedAttachmentTarget::Texture: case TrackedAttachmentTarget::Texture:
MOBILEGL_ASSERT(s_textureManager != nullptr, "EndRenderPass: texture manager is null"); MOBILEGL_ASSERT(s_textureManager != nullptr, "EndRenderPass: texture manager is null");
if (const auto texture = trackedAttachment.texture.lock()) {
s_textureManager->UpdateTrackedImageLayoutAfterAttachmentWrite( s_textureManager->UpdateTrackedImageLayoutAfterAttachmentWrite(
commandBuffer, commandBuffer,
trackedAttachment.texture, texture.get(),
trackedAttachment.textureMipLevel, trackedAttachment.textureMipLevel,
trackedAttachment.finalLayout); trackedAttachment.finalLayout);
}
break; break;
case TrackedAttachmentTarget::SwapchainColor: case TrackedAttachmentTarget::SwapchainColor:
MOBILEGL_ASSERT(s_swapchainObject != nullptr, "EndRenderPass: swapchain object is null"); MOBILEGL_ASSERT(s_swapchainObject != nullptr, "EndRenderPass: swapchain object is null");
@@ -26,12 +26,12 @@ namespace MobileGL::MG_Backend::DirectVulkan {
struct PendingClearAttachmentInfo { struct PendingClearAttachmentInfo {
Uint32 attachmentIndex = 0; Uint32 attachmentIndex = 0;
MG_State::GLState::ITextureObject* texture = nullptr; PendingClearKey key{};
}; };
struct TrackedAttachmentLayoutInfo { struct TrackedAttachmentLayoutInfo {
TrackedAttachmentTarget target = TrackedAttachmentTarget::Texture; TrackedAttachmentTarget target = TrackedAttachmentTarget::Texture;
MG_State::GLState::ITextureObject* texture = nullptr; WeakPtr<MG_State::GLState::ITextureObject> texture;
Uint32 textureMipLevel = 0; Uint32 textureMipLevel = 0;
Uint32 swapchainImageIndex = 0; Uint32 swapchainImageIndex = 0;
VkImageLayout finalLayout = VK_IMAGE_LAYOUT_UNDEFINED; VkImageLayout finalLayout = VK_IMAGE_LAYOUT_UNDEFINED;
@@ -45,6 +45,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
DepthStencilAttachmentLoadInfo ResolveDepthStencilAttachmentLoadInfo( DepthStencilAttachmentLoadInfo ResolveDepthStencilAttachmentLoadInfo(
VkImageLayout trackedLayout, Bool clearDepth, Bool clearStencil); VkImageLayout trackedLayout, Bool clearDepth, Bool clearStencil);
IntVec2 ResolveRenderPassFramebufferExtent(Bool isDefaultFbo, const TextureSize& attachmentExtent,
VkExtent2D swapchainExtent);
struct RenderPassEntry { struct RenderPassEntry {
static inline VkDevice s_device; static inline VkDevice s_device;
@@ -58,6 +60,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Uint32 attachmentCount = 0; Uint32 attachmentCount = 0;
Uint32 colorAttachmentCount = 0; Uint32 colorAttachmentCount = 0;
Bool hasDepthStencilAttachment = false; Bool hasDepthStencilAttachment = false;
VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT;
IntVec2 extent = {0, 0}; IntVec2 extent = {0, 0};
Uint32 subpass = 0; Uint32 subpass = 0;
@@ -73,6 +76,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
std::swap(attachmentCount, that.attachmentCount); std::swap(attachmentCount, that.attachmentCount);
std::swap(colorAttachmentCount, that.colorAttachmentCount); std::swap(colorAttachmentCount, that.colorAttachmentCount);
std::swap(hasDepthStencilAttachment, that.hasDepthStencilAttachment); std::swap(hasDepthStencilAttachment, that.hasDepthStencilAttachment);
std::swap(sampleCount, that.sampleCount);
std::swap(extent, that.extent); std::swap(extent, that.extent);
std::swap(subpass, that.subpass); std::swap(subpass, that.subpass);
} }
@@ -86,6 +90,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Uint32 attachmentCount, Uint32 attachmentCount,
Uint32 colorAttachmentCount, Uint32 colorAttachmentCount,
Bool hasDepthStencilAttachment, Bool hasDepthStencilAttachment,
VkSampleCountFlagBits sampleCount,
IntVec2 extent, int subpass): IntVec2 extent, int subpass):
hash(hash), hash(hash),
renderPass(renderpass), renderPass(renderpass),
@@ -96,6 +101,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
attachmentCount(attachmentCount), attachmentCount(attachmentCount),
colorAttachmentCount(colorAttachmentCount), colorAttachmentCount(colorAttachmentCount),
hasDepthStencilAttachment(hasDepthStencilAttachment), hasDepthStencilAttachment(hasDepthStencilAttachment),
sampleCount(sampleCount),
extent(extent), extent(extent),
subpass(subpass) subpass(subpass)
{} {}
@@ -46,6 +46,41 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Uint32 arrayLayers = 1; Uint32 arrayLayers = 1;
}; };
static Bool IsMultisampleTextureUploadTarget(TextureUploadTarget target) {
return target == TextureUploadTarget::Texture2DMultisample ||
target == TextureUploadTarget::ProxyTexture2DMultisample ||
target == TextureUploadTarget::Texture2DMultisampleArray ||
target == TextureUploadTarget::ProxyTexture2DMultisampleArray;
}
static Bool TryResolveSampleCountFlagBits(Int requestedSamples, VkSampleCountFlagBits& outSampleCount) {
switch (requestedSamples) {
case 1:
outSampleCount = VK_SAMPLE_COUNT_1_BIT;
return true;
case 2:
outSampleCount = VK_SAMPLE_COUNT_2_BIT;
return true;
case 4:
outSampleCount = VK_SAMPLE_COUNT_4_BIT;
return true;
case 8:
outSampleCount = VK_SAMPLE_COUNT_8_BIT;
return true;
case 16:
outSampleCount = VK_SAMPLE_COUNT_16_BIT;
return true;
case 32:
outSampleCount = VK_SAMPLE_COUNT_32_BIT;
return true;
case 64:
outSampleCount = VK_SAMPLE_COUNT_64_BIT;
return true;
default:
return false;
}
}
static Bool IsCubeMapFaceUploadTarget(TextureUploadTarget target) { static Bool IsCubeMapFaceUploadTarget(TextureUploadTarget target) {
return target >= TextureUploadTarget::CubeMapPositiveX && return target >= TextureUploadTarget::CubeMapPositiveX &&
target <= TextureUploadTarget::CubeMapNegativeZ; target <= TextureUploadTarget::CubeMapNegativeZ;
@@ -71,6 +106,12 @@ namespace MobileGL::MG_Backend::DirectVulkan {
} }
} }
static VkImageLayout ResolveSampledReadOnlyLayout(VkImageAspectFlags aspectMask) {
return (aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != 0
? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL
: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
}
static void GetImageTransitionSourceState(VkImageLayout oldLayout, static void GetImageTransitionSourceState(VkImageLayout oldLayout,
VkPipelineStageFlags& outSrcStageMask, VkPipelineStageFlags& outSrcStageMask,
VkAccessFlags& outSrcAccessMask) { VkAccessFlags& outSrcAccessMask) {
@@ -115,6 +156,14 @@ namespace MobileGL::MG_Backend::DirectVulkan {
} }
} }
VkTextureManager::TextureIdentity VkTextureManager::MakeTextureIdentity(
MG_State::GLState::ITextureObject* texture) {
return TextureIdentity{
.texture = texture,
.lifetimeId = texture ? texture->GetLifetimeId() : 0,
};
}
static void GetImageTransitionDestinationState(VkImageLayout newLayout, static void GetImageTransitionDestinationState(VkImageLayout newLayout,
VkPipelineStageFlags& outDstStageMask, VkPipelineStageFlags& outDstStageMask,
VkAccessFlags& outDstAccessMask) { VkAccessFlags& outDstAccessMask) {
@@ -462,6 +511,20 @@ namespace MobileGL::MG_Backend::DirectVulkan {
case TextureUploadTarget::ProxyTextureRectangle: case TextureUploadTarget::ProxyTextureRectangle:
outShape = {}; outShape = {};
return true; return true;
case TextureUploadTarget::Texture2DMultisample:
case TextureUploadTarget::ProxyTexture2DMultisample:
outShape = {};
return true;
case TextureUploadTarget::Texture2DMultisampleArray:
case TextureUploadTarget::ProxyTexture2DMultisampleArray:
MOBILEGL_ASSERT(texelSize.z() > 0,
"TryResolveTextureShapeInfo: invalid 2D multisample array depth=%d for textureId=%d",
texelSize.z(), texture.GetExternalIndex());
outShape.imageType = VK_IMAGE_TYPE_2D;
outShape.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
outShape.depth = 1;
outShape.arrayLayers = static_cast<Uint32>(texelSize.z());
return true;
case TextureUploadTarget::Texture3D: case TextureUploadTarget::Texture3D:
case TextureUploadTarget::ProxyTexture3D: case TextureUploadTarget::ProxyTexture3D:
MOBILEGL_ASSERT(texelSize.z() > 0, MOBILEGL_ASSERT(texelSize.z() > 0,
@@ -525,6 +588,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
void VkTextureManager::Shutdown() { void VkTextureManager::Shutdown() {
DestroyDeferredReleases(); DestroyDeferredReleases();
m_textureResources.clear(); m_textureResources.clear();
m_aliveObjects.clear();
m_device = VK_NULL_HANDLE; m_device = VK_NULL_HANDLE;
m_physicalDevice = VK_NULL_HANDLE; m_physicalDevice = VK_NULL_HANDLE;
@@ -545,28 +609,56 @@ namespace MobileGL::MG_Backend::DirectVulkan {
CollectDeferredReleases(frameIndex); CollectDeferredReleases(frameIndex);
} }
VkTextureManager::TextureResource* VkTextureManager::SyncTextureAndGetDescriptor(MG_State::GLState::ITextureObject& texture) { void VkTextureManager::EraseTrackedTexture(const TextureIdentity& identity) {
MOBILEGL_ASSERT(m_device != VK_NULL_HANDLE, "SyncTextureAndGetDescriptor: m_device == VK_NULL_HANDLE"); auto resourceIt = m_textureResources.find(identity);
auto aliveIt = m_aliveObjects.find(&texture);
if (aliveIt != m_aliveObjects.end() && aliveIt->second.expired()) {
auto resourceIt = m_textureResources.find(&texture);
if (resourceIt != m_textureResources.end()) { if (resourceIt != m_textureResources.end()) {
DeferResourceRelease(Move(resourceIt->second)); DeferResourceRelease(Move(resourceIt->second));
m_textureResources.erase(resourceIt); m_textureResources.erase(resourceIt);
} }
m_aliveObjects.erase(aliveIt); m_aliveObjects.erase(identity);
}
void VkTextureManager::PruneStaleTextureAliases(MG_State::GLState::ITextureObject* texture) {
if (texture == nullptr) {
return;
}
Vector<TextureIdentity> staleAliases;
staleAliases.reserve(m_aliveObjects.size());
for (auto it = m_aliveObjects.begin(); it != m_aliveObjects.end(); ++it) {
if (it->first.texture != texture) {
continue;
}
const auto liveTexture = it->second.lock();
if (!liveTexture || liveTexture.get() != texture ||
liveTexture->GetLifetimeId() != it->first.lifetimeId) {
staleAliases.emplace_back(it->first);
}
}
for (const auto& identity : staleAliases) {
EraseTrackedTexture(identity);
}
}
VkTextureManager::TextureResource* VkTextureManager::SyncTextureAndGetDescriptor(MG_State::GLState::ITextureObject& texture) {
MOBILEGL_ASSERT(m_device != VK_NULL_HANDLE, "SyncTextureAndGetDescriptor: m_device == VK_NULL_HANDLE");
const TextureIdentity identity = MakeTextureIdentity(&texture);
auto aliveIt = m_aliveObjects.find(identity);
if (aliveIt != m_aliveObjects.end() && aliveIt->second.expired()) {
EraseTrackedTexture(aliveIt->first);
} }
const auto& liveTexture = MG_State::pGLContext->GetTextureObject(texture.GetExternalIndex()); const auto& liveTexture = MG_State::pGLContext->GetTextureObject(texture.GetExternalIndex());
if (liveTexture && liveTexture.get() == &texture) { if (liveTexture && liveTexture.get() == &texture) {
m_aliveObjects[&texture] = WeakPtr<MG_State::GLState::ITextureObject>(liveTexture); m_aliveObjects[identity] = WeakPtr<MG_State::GLState::ITextureObject>(liveTexture);
PruneStaleTextureAliases(&texture);
} }
auto it = m_textureResources.find(&texture); auto it = m_textureResources.find(identity);
if (it == m_textureResources.end()) { if (it == m_textureResources.end()) {
TextureResource initial{}; TextureResource initial{};
auto [insertIt, _] = m_textureResources.emplace(&texture, Move(initial)); auto [insertIt, _] = m_textureResources.emplace(identity, Move(initial));
it = insertIt; it = insertIt;
} }
@@ -594,7 +686,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
} }
perMipView = CreateImageView(resource->image, resource->format, resource->aspect, resource->viewType, perMipView = CreateImageView(resource->image, resource->format, resource->aspect, resource->viewType,
mipLevel, 1, resource->arrayLayers); mipLevel, 1, 0, resource->arrayLayers);
if (perMipView == VK_NULL_HANDLE) { if (perMipView == VK_NULL_HANDLE) {
MGLOG_D("%s: CreateImageView failed for textureId=%d mipLevel=%u", __func__, texture.GetExternalIndex(), mipLevel); MGLOG_D("%s: CreateImageView failed for textureId=%d mipLevel=%u", __func__, texture.GetExternalIndex(), mipLevel);
return VK_NULL_HANDLE; return VK_NULL_HANDLE;
@@ -603,6 +695,53 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return perMipView; return perMipView;
} }
VkImageView VkTextureManager::GetOrCreateAttachmentViewAtMipLevel(MG_State::GLState::ITextureObject& texture,
Uint32 mipLevel, Uint32 baseArrayLayer,
Uint32 layerCount,
VkImageViewType viewType) {
TextureResource* resource = SyncTextureAndGetDescriptor(texture);
if (resource == nullptr || resource->image == VK_NULL_HANDLE || mipLevel >= resource->mipLevels) {
return VK_NULL_HANDLE;
}
if (layerCount == 0 || baseArrayLayer >= resource->arrayLayers ||
baseArrayLayer + layerCount > resource->arrayLayers) {
MGLOG_D("%s: invalid layer span [%u, %u) for textureId=%d arrayLayers=%u",
__func__, baseArrayLayer, baseArrayLayer + layerCount, texture.GetExternalIndex(),
resource->arrayLayers);
return VK_NULL_HANDLE;
}
if (baseArrayLayer == 0 && layerCount == resource->arrayLayers && viewType == resource->viewType) {
return GetOrCreateViewAtMipLevel(texture, mipLevel);
}
const TextureResource::AttachmentViewKey key{
.mipLevel = mipLevel,
.baseArrayLayer = baseArrayLayer,
.layerCount = layerCount,
.viewType = viewType,
};
auto it = resource->attachmentViews.find(key);
if (it == resource->attachmentViews.end()) {
it = resource->attachmentViews.emplace(key, VK_NULL_HANDLE).first;
}
VkImageView& attachmentView = it->second;
if (attachmentView != VK_NULL_HANDLE) {
return attachmentView;
}
attachmentView = CreateImageView(resource->image, resource->format, resource->aspect, viewType,
mipLevel, 1, baseArrayLayer, layerCount);
if (attachmentView == VK_NULL_HANDLE) {
MGLOG_D("%s: CreateImageView failed for textureId=%d mipLevel=%u baseArrayLayer=%u layerCount=%u viewType=%d",
__func__, texture.GetExternalIndex(), mipLevel, baseArrayLayer, layerCount, static_cast<Int>(viewType));
resource->attachmentViews.erase(it);
return VK_NULL_HANDLE;
}
return attachmentView;
}
VkImageView VkTextureManager::GetOrCreateSampledViewAtMipLevel(MG_State::GLState::ITextureObject& texture, VkImageView VkTextureManager::GetOrCreateSampledViewAtMipLevel(MG_State::GLState::ITextureObject& texture,
Uint32 mipLevel) { Uint32 mipLevel) {
TextureResource* resource = SyncTextureAndGetDescriptor(texture); TextureResource* resource = SyncTextureAndGetDescriptor(texture);
@@ -623,7 +762,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
const VkComponentMapping sampledComponents = ResolveSampledViewComponents(texture, formatInfo); const VkComponentMapping sampledComponents = ResolveSampledViewComponents(texture, formatInfo);
const VkImageAspectFlags sampledAspect = ResolveSampledImageViewAspectMask(resource->aspect); const VkImageAspectFlags sampledAspect = ResolveSampledImageViewAspectMask(resource->aspect);
perMipSampledView = CreateImageView(resource->image, resource->format, sampledAspect, resource->viewType, perMipSampledView = CreateImageView(resource->image, resource->format, sampledAspect, resource->viewType,
mipLevel, 1, resource->arrayLayers, &sampledComponents); mipLevel, 1, 0, resource->arrayLayers, &sampledComponents);
if (perMipSampledView == VK_NULL_HANDLE) { if (perMipSampledView == VK_NULL_HANDLE) {
MGLOG_D("%s: CreateImageView failed for textureId=%d mipLevel=%u", __func__, texture.GetExternalIndex(), MGLOG_D("%s: CreateImageView failed for textureId=%d mipLevel=%u", __func__, texture.GetExternalIndex(),
mipLevel); mipLevel);
@@ -635,7 +774,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
void VkTextureManager::UpdateTrackedImageLayout(MG_State::GLState::ITextureObject* texture, VkImageLayout newLayout) { void VkTextureManager::UpdateTrackedImageLayout(MG_State::GLState::ITextureObject* texture, VkImageLayout newLayout) {
MOBILEGL_ASSERT(texture != nullptr, "UpdateTrackedImageLayout: texture is null"); MOBILEGL_ASSERT(texture != nullptr, "UpdateTrackedImageLayout: texture is null");
auto it = m_textureResources.find(texture); auto it = m_textureResources.find(MakeTextureIdentity(texture));
MOBILEGL_ASSERT(it != m_textureResources.end(), MOBILEGL_ASSERT(it != m_textureResources.end(),
"UpdateTrackedImageLayout: textureId=%d has no tracked resource", texture->GetExternalIndex()); "UpdateTrackedImageLayout: textureId=%d has no tracked resource", texture->GetExternalIndex());
MOBILEGL_ASSERT(it->second.image != VK_NULL_HANDLE, MOBILEGL_ASSERT(it->second.image != VK_NULL_HANDLE,
@@ -648,7 +787,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Uint32 writtenMipLevel, Uint32 writtenMipLevel,
VkImageLayout newLayout) { VkImageLayout newLayout) {
MOBILEGL_ASSERT(texture != nullptr, "UpdateTrackedImageLayoutAfterAttachmentWrite: texture is null"); MOBILEGL_ASSERT(texture != nullptr, "UpdateTrackedImageLayoutAfterAttachmentWrite: texture is null");
auto it = m_textureResources.find(texture); auto it = m_textureResources.find(MakeTextureIdentity(texture));
MOBILEGL_ASSERT(it != m_textureResources.end(), MOBILEGL_ASSERT(it != m_textureResources.end(),
"UpdateTrackedImageLayoutAfterAttachmentWrite: textureId=%d has no tracked resource", "UpdateTrackedImageLayoutAfterAttachmentWrite: textureId=%d has no tracked resource",
texture->GetExternalIndex()); texture->GetExternalIndex());
@@ -753,6 +892,11 @@ namespace MobileGL::MG_Backend::DirectVulkan {
if (resource == nullptr) { if (resource == nullptr) {
return false; return false;
} }
if (resource->sampleCount != VK_SAMPLE_COUNT_1_BIT) {
MGLOG_D("TransitionTextureForStorageImage: multisample textureId=%d is not exposed as a storage image",
texture.GetExternalIndex());
return false;
}
if (resource->layout == VK_IMAGE_LAYOUT_GENERAL) { if (resource->layout == VK_IMAGE_LAYOUT_GENERAL) {
return true; return true;
} }
@@ -813,20 +957,18 @@ namespace MobileGL::MG_Backend::DirectVulkan {
if (m_gcCounter != 0) { if (m_gcCounter != 0) {
return 0; return 0;
} }
SizeT count = 0;
for (auto it = m_aliveObjects.begin(); it != m_aliveObjects.end();) { Vector<MG_State::GLState::ITextureObject*> expiredTextures;
auto current = it++; expiredTextures.reserve(m_aliveObjects.size());
if (current->second.expired()) { for (auto it = m_aliveObjects.begin(); it != m_aliveObjects.end(); ++it) {
auto resourceIt = m_textureResources.find(current->first); if (it->second.expired()) {
if (resourceIt != m_textureResources.end()) { expiredTextures.emplace_back(it->first.texture);
DeferResourceRelease(Move(resourceIt->second));
m_textureResources.erase(resourceIt);
}
m_aliveObjects.erase(current);
++count;
} }
} }
return count; for (auto* texture : expiredTextures) {
PruneStaleTextureAliases(texture);
}
return expiredTextures.size();
} }
Bool VkTextureManager::SyncTexture(MG_State::GLState::ITextureObject &texture, Bool VkTextureManager::SyncTexture(MG_State::GLState::ITextureObject &texture,
@@ -905,7 +1047,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
MGLOG_D("%s: no mip levels", __func__); MGLOG_D("%s: no mip levels", __func__);
return false; return false;
} }
const Uint32 backingMipLevels = std::max(mipLevels, ComputeFullMipLevelCount(texelSize)); const Bool isMultisampleTexture = IsMultisampleTextureUploadTarget(uploadTarget);
const Uint32 backingMipLevels =
isMultisampleTexture ? 1u : std::max(mipLevels, ComputeFullMipLevelCount(texelSize));
TextureShapeInfo shapeInfo{}; TextureShapeInfo shapeInfo{};
const Bool supportedShape = TryResolveTextureShapeInfo(texture, uploadTarget, texelSize, shapeInfo); const Bool supportedShape = TryResolveTextureShapeInfo(texture, uploadTarget, texelSize, shapeInfo);
MOBILEGL_ASSERT(supportedShape, MOBILEGL_ASSERT(supportedShape,
@@ -919,6 +1063,14 @@ namespace MobileGL::MG_Backend::DirectVulkan {
MGLOG_D("%s: not Texture2D, unsupported", __func__); MGLOG_D("%s: not Texture2D, unsupported", __func__);
return false; return false;
} }
VkSampleCountFlagBits resolvedSampleCount = VK_SAMPLE_COUNT_1_BIT;
if (isMultisampleTexture &&
!TryResolveSampleCountFlagBits(texture.GetSamples(), resolvedSampleCount)) {
MGLOG_D("%s: unsupported multisample count=%d for textureId=%d target=%s", __func__,
texture.GetSamples(), texture.GetExternalIndex(),
MG_Util::ConvertTextureUploadTargetToString(uploadTarget).c_str());
return false;
}
const Bool compatible = resource.image != VK_NULL_HANDLE && resource.format == format && const Bool compatible = resource.image != VK_NULL_HANDLE && resource.format == format &&
resource.extent.width == static_cast<Uint32>(texelSize.x()) && resource.extent.width == static_cast<Uint32>(texelSize.x()) &&
@@ -926,6 +1078,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
resource.depth == shapeInfo.depth && resource.depth == shapeInfo.depth &&
resource.arrayLayers == shapeInfo.arrayLayers && resource.arrayLayers == shapeInfo.arrayLayers &&
resource.viewType == shapeInfo.viewType && resource.viewType == shapeInfo.viewType &&
resource.sampleCount == resolvedSampleCount &&
resource.mipLevels == backingMipLevels; resource.mipLevels == backingMipLevels;
if (compatible) { if (compatible) {
if (resource.perMipViews.size() != backingMipLevels) { if (resource.perMipViews.size() != backingMipLevels) {
@@ -945,6 +1098,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
resource.depth == shapeInfo.depth && resource.depth == shapeInfo.depth &&
resource.arrayLayers == shapeInfo.arrayLayers && resource.arrayLayers == shapeInfo.arrayLayers &&
resource.viewType == shapeInfo.viewType && resource.viewType == shapeInfo.viewType &&
resource.sampleCount == resolvedSampleCount &&
resolvedSampleCount == VK_SAMPLE_COUNT_1_BIT &&
resource.mipLevels < backingMipLevels && resource.mipLevels < backingMipLevels &&
resource.layout != VK_IMAGE_LAYOUT_UNDEFINED; resource.layout != VK_IMAGE_LAYOUT_UNDEFINED;
@@ -972,16 +1127,33 @@ namespace MobileGL::MG_Backend::DirectVulkan {
VkFormatProperties formatProperties{}; VkFormatProperties formatProperties{};
vkGetPhysicalDeviceFormatProperties(m_physicalDevice, format, &formatProperties); vkGetPhysicalDeviceFormatProperties(m_physicalDevice, format, &formatProperties);
const Bool supportsStorageImage = const Bool supportsStorageImage =
!isMultisampleTexture &&
(aspect & VK_IMAGE_ASPECT_COLOR_BIT) != 0 && (aspect & VK_IMAGE_ASPECT_COLOR_BIT) != 0 &&
(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) != 0; (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) != 0;
imageInfo.usage = imageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT |
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
(supportsStorageImage ? VK_IMAGE_USAGE_STORAGE_BIT : 0) | (supportsStorageImage ? VK_IMAGE_USAGE_STORAGE_BIT : 0) |
((aspect & VK_IMAGE_ASPECT_COLOR_BIT) ? ((aspect & VK_IMAGE_ASPECT_COLOR_BIT) ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT : 0) |
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT : 0) | (((aspect & VK_IMAGE_ASPECT_DEPTH_BIT) || (aspect & VK_IMAGE_ASPECT_STENCIL_BIT)) ?
((aspect & VK_IMAGE_ASPECT_DEPTH_BIT || aspect & VK_IMAGE_ASPECT_STENCIL_BIT) ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT :
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : 0); 0);
imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; if (!isMultisampleTexture) {
imageInfo.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
}
imageInfo.samples = resolvedSampleCount;
if (isMultisampleTexture) {
VkImageFormatProperties imageFormatProperties{};
const VkResult imageFormatResult = vkGetPhysicalDeviceImageFormatProperties(
m_physicalDevice, format, imageInfo.imageType, imageInfo.tiling, imageInfo.usage,
imageInfo.flags, &imageFormatProperties);
if (imageFormatResult != VK_SUCCESS ||
(imageFormatProperties.sampleCounts & resolvedSampleCount) == 0) {
MGLOG_D("%s: sampleCount=%d is unsupported for textureId=%d target=%s format=%d usage=0x%x",
__func__, texture.GetSamples(), texture.GetExternalIndex(),
MG_Util::ConvertTextureUploadTargetToString(uploadTarget).c_str(),
static_cast<Int>(format), static_cast<Uint32>(imageInfo.usage));
return false;
}
}
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
VmaAllocationCreateInfo allocationInfo{}; VmaAllocationCreateInfo allocationInfo{};
allocationInfo.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE; allocationInfo.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
@@ -1001,6 +1173,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
resource.format = format; resource.format = format;
resource.aspect = aspect; resource.aspect = aspect;
resource.viewType = shapeInfo.viewType; resource.viewType = shapeInfo.viewType;
resource.sampleCount = resolvedSampleCount;
resource.syncedTextureParamsVersion = 0; resource.syncedTextureParamsVersion = 0;
if (preservedResource) { if (preservedResource) {
@@ -1116,13 +1289,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
const TextureFormatInfo formatInfo = ResolveTextureFormatInfo(texture.GetFormat()); const TextureFormatInfo formatInfo = ResolveTextureFormatInfo(texture.GetFormat());
const VkComponentMapping sampledComponents = ResolveSampledViewComponents(texture, formatInfo); const VkComponentMapping sampledComponents = ResolveSampledViewComponents(texture, formatInfo);
resource.fullView = CreateImageView(resource.image, resource.format, resource.aspect, resource.viewType, resource.fullView = CreateImageView(resource.image, resource.format, resource.aspect, resource.viewType,
baseMipLevel, levelCount, resource.arrayLayers); baseMipLevel, levelCount, 0, resource.arrayLayers, &sampledComponents);
if (resource.fullView == VK_NULL_HANDLE) { if (resource.fullView == VK_NULL_HANDLE) {
return false; return false;
} }
const VkImageAspectFlags sampledAspect = ResolveSampledImageViewAspectMask(resource.aspect); const VkImageAspectFlags sampledAspect = ResolveSampledImageViewAspectMask(resource.aspect);
resource.sampledView = CreateImageView(resource.image, resource.format, sampledAspect, resource.viewType, resource.sampledView = CreateImageView(resource.image, resource.format, sampledAspect, resource.viewType,
baseMipLevel, levelCount, resource.arrayLayers, &sampledComponents); baseMipLevel, levelCount, 0, resource.arrayLayers, &sampledComponents);
if (resource.sampledView == VK_NULL_HANDLE) { if (resource.sampledView == VK_NULL_HANDLE) {
return false; return false;
} }
@@ -1135,6 +1308,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
VkImageView VkTextureManager::CreateImageView(VkImage image, VkFormat format, VkImageAspectFlags aspect, VkImageView VkTextureManager::CreateImageView(VkImage image, VkFormat format, VkImageAspectFlags aspect,
VkImageViewType viewType, Uint32 baseMipLevel, Uint32 levelCount, VkImageViewType viewType, Uint32 baseMipLevel, Uint32 levelCount,
Uint32 baseArrayLayer,
Uint32 layerCount, Uint32 layerCount,
const VkComponentMapping* components) const { const VkComponentMapping* components) const {
VkImageViewCreateInfo viewInfo{}; VkImageViewCreateInfo viewInfo{};
@@ -1149,7 +1323,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
viewInfo.subresourceRange.aspectMask = aspect; viewInfo.subresourceRange.aspectMask = aspect;
viewInfo.subresourceRange.baseMipLevel = baseMipLevel; viewInfo.subresourceRange.baseMipLevel = baseMipLevel;
viewInfo.subresourceRange.levelCount = levelCount; viewInfo.subresourceRange.levelCount = levelCount;
viewInfo.subresourceRange.baseArrayLayer = 0; viewInfo.subresourceRange.baseArrayLayer = baseArrayLayer;
viewInfo.subresourceRange.layerCount = layerCount; viewInfo.subresourceRange.layerCount = layerCount;
VkImageView view = VK_NULL_HANDLE; VkImageView view = VK_NULL_HANDLE;
@@ -1306,17 +1480,18 @@ namespace MobileGL::MG_Backend::DirectVulkan {
1, &copy); 1, &copy);
} }
const VkImageLayout finalLayout = ResolveSampledReadOnlyLayout(aspectMask);
VkImageLayout uploadLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; VkImageLayout uploadLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
ok = TransitionImageLayout(commandBuffer, outResource.image, ok = TransitionImageLayout(commandBuffer, outResource.image,
uploadLayout, uploadLayout,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, finalLayout,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
kGraphicsSampledReadStages, kGraphicsSampledReadStages,
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT,
VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_SHADER_READ_BIT,
aspectMask, 0, outResource.mipLevels, outResource.arrayLayers); aspectMask, 0, outResource.mipLevels, outResource.arrayLayers);
MOBILEGL_ASSERT(ok, "TransitionImageLayout to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL failed"); MOBILEGL_ASSERT(ok, "TransitionImageLayout to sampled read-only layout failed");
outResource.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; outResource.layout = finalLayout;
VK_VERIFY(vkEndCommandBuffer(commandBuffer), "vkEndCommandBuffer(texture)"); VK_VERIFY(vkEndCommandBuffer(commandBuffer), "vkEndCommandBuffer(texture)");
@@ -1344,7 +1519,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
for (const auto& item : uploadItems) { for (const auto& item : uploadItems) {
mipmapTexture.MarkStorageDirty(item.target, item.level, false); mipmapTexture.MarkStorageDirty(item.target, item.level, false);
} }
outResource.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; outResource.layout = finalLayout;
return true; return true;
} }
@@ -12,6 +12,7 @@
#include <Includes.h> #include <Includes.h>
#include <MG_State/GLState/TextureState/TextureObject.h> #include <MG_State/GLState/TextureState/TextureObject.h>
#include <vk_mem_alloc.h> #include <vk_mem_alloc.h>
#include <unordered_map>
namespace MobileGL::MG_State::GLState { namespace MobileGL::MG_State::GLState {
class ITextureObject; class ITextureObject;
@@ -20,6 +21,23 @@ class ITextureObject;
namespace MobileGL::MG_Backend::DirectVulkan { namespace MobileGL::MG_Backend::DirectVulkan {
class VkTextureManager { class VkTextureManager {
public: public:
struct TextureIdentity {
MG_State::GLState::ITextureObject* texture = nullptr;
Uint64 lifetimeId = 0;
Bool operator==(const TextureIdentity& other) const {
return texture == other.texture && lifetimeId == other.lifetimeId;
}
};
struct TextureIdentityHash {
SizeT operator()(const TextureIdentity& key) const {
SizeT hash = std::hash<MG_State::GLState::ITextureObject*>{}(key.texture);
hash ^= std::hash<Uint64>{}(key.lifetimeId) + 0x9e3779b9u + (hash << 6) + (hash >> 2);
return hash;
}
};
struct InitInfo { struct InitInfo {
VkDevice device = VK_NULL_HANDLE; VkDevice device = VK_NULL_HANDLE;
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
@@ -30,12 +48,38 @@ public:
}; };
struct TextureResource { struct TextureResource {
struct AttachmentViewKey {
Uint32 mipLevel = 0;
Uint32 baseArrayLayer = 0;
Uint32 layerCount = 1;
VkImageViewType viewType = VK_IMAGE_VIEW_TYPE_2D;
Bool operator==(const AttachmentViewKey& other) const {
return mipLevel == other.mipLevel &&
baseArrayLayer == other.baseArrayLayer &&
layerCount == other.layerCount &&
viewType == other.viewType;
}
};
struct AttachmentViewKeyHash {
SizeT operator()(const AttachmentViewKey& key) const {
SizeT hash = std::hash<Uint32>{}(key.mipLevel);
hash ^= std::hash<Uint32>{}(key.baseArrayLayer) + 0x9e3779b9u + (hash << 6) + (hash >> 2);
hash ^= std::hash<Uint32>{}(key.layerCount) + 0x9e3779b9u + (hash << 6) + (hash >> 2);
hash ^= std::hash<Uint32>{}(static_cast<Uint32>(key.viewType)) +
0x9e3779b9u + (hash << 6) + (hash >> 2);
return hash;
}
};
VkImage image = VK_NULL_HANDLE; VkImage image = VK_NULL_HANDLE;
VmaAllocation allocation = nullptr; VmaAllocation allocation = nullptr;
VkImageView fullView = VK_NULL_HANDLE; VkImageView fullView = VK_NULL_HANDLE;
VkImageView sampledView = VK_NULL_HANDLE; VkImageView sampledView = VK_NULL_HANDLE;
Vector<VkImageView> perMipViews; Vector<VkImageView> perMipViews;
Vector<VkImageView> perMipSampledViews; Vector<VkImageView> perMipSampledViews;
UnorderedMap<AttachmentViewKey, VkImageView, AttachmentViewKeyHash> attachmentViews;
VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED; VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED;
VkExtent2D extent = {0, 0}; VkExtent2D extent = {0, 0};
Uint32 depth = 1; Uint32 depth = 1;
@@ -46,6 +90,7 @@ public:
VkFormat format = VK_FORMAT_UNDEFINED; VkFormat format = VK_FORMAT_UNDEFINED;
VkImageAspectFlags aspect = VK_IMAGE_ASPECT_NONE; VkImageAspectFlags aspect = VK_IMAGE_ASPECT_NONE;
VkImageViewType viewType = VK_IMAGE_VIEW_TYPE_2D; VkImageViewType viewType = VK_IMAGE_VIEW_TYPE_2D;
VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT;
Uint16 syncedTextureParamsVersion = 0; Uint16 syncedTextureParamsVersion = 0;
TextureResource() = default; TextureResource() = default;
@@ -57,6 +102,7 @@ public:
std::swap(this->sampledView, that.sampledView); std::swap(this->sampledView, that.sampledView);
std::swap(this->perMipViews, that.perMipViews); std::swap(this->perMipViews, that.perMipViews);
std::swap(this->perMipSampledViews, that.perMipSampledViews); std::swap(this->perMipSampledViews, that.perMipSampledViews);
std::swap(this->attachmentViews, that.attachmentViews);
std::swap(this->layout, that.layout); std::swap(this->layout, that.layout);
std::swap(this->extent, that.extent); std::swap(this->extent, that.extent);
std::swap(this->depth, that.depth); std::swap(this->depth, that.depth);
@@ -67,6 +113,7 @@ public:
std::swap(this->format, that.format); std::swap(this->format, that.format);
std::swap(this->aspect, that.aspect); std::swap(this->aspect, that.aspect);
std::swap(this->viewType, that.viewType); std::swap(this->viewType, that.viewType);
std::swap(this->sampleCount, that.sampleCount);
std::swap(this->syncedTextureParamsVersion, that.syncedTextureParamsVersion); std::swap(this->syncedTextureParamsVersion, that.syncedTextureParamsVersion);
} }
@@ -87,6 +134,11 @@ public:
vkDestroyImageView(s_device, sampledView, nullptr); vkDestroyImageView(s_device, sampledView, nullptr);
} }
} }
for (const auto& [_, attachmentView] : attachmentViews) {
if (attachmentView != VK_NULL_HANDLE) {
vkDestroyImageView(s_device, attachmentView, nullptr);
}
}
if (image != VK_NULL_HANDLE && allocation != nullptr) { if (image != VK_NULL_HANDLE && allocation != nullptr) {
vmaDestroyImage(s_allocator, image, allocation); vmaDestroyImage(s_allocator, image, allocation);
} }
@@ -94,6 +146,7 @@ public:
sampledView = VK_NULL_HANDLE; sampledView = VK_NULL_HANDLE;
perMipViews.clear(); perMipViews.clear();
perMipSampledViews.clear(); perMipSampledViews.clear();
attachmentViews.clear();
image = VK_NULL_HANDLE; image = VK_NULL_HANDLE;
allocation = nullptr; allocation = nullptr;
layout = VK_IMAGE_LAYOUT_UNDEFINED; layout = VK_IMAGE_LAYOUT_UNDEFINED;
@@ -106,6 +159,7 @@ public:
format = VK_FORMAT_UNDEFINED; format = VK_FORMAT_UNDEFINED;
aspect = VK_IMAGE_ASPECT_NONE; aspect = VK_IMAGE_ASPECT_NONE;
viewType = VK_IMAGE_VIEW_TYPE_2D; viewType = VK_IMAGE_VIEW_TYPE_2D;
sampleCount = VK_SAMPLE_COUNT_1_BIT;
syncedTextureParamsVersion = 0; syncedTextureParamsVersion = 0;
} }
@@ -124,6 +178,9 @@ public:
TextureResource* SyncTextureAndGetDescriptor( TextureResource* SyncTextureAndGetDescriptor(
MG_State::GLState::ITextureObject& texture); MG_State::GLState::ITextureObject& texture);
VkImageView GetOrCreateViewAtMipLevel(MG_State::GLState::ITextureObject& texture, Uint32 mipLevel); VkImageView GetOrCreateViewAtMipLevel(MG_State::GLState::ITextureObject& texture, Uint32 mipLevel);
VkImageView GetOrCreateAttachmentViewAtMipLevel(MG_State::GLState::ITextureObject& texture, Uint32 mipLevel,
Uint32 baseArrayLayer, Uint32 layerCount,
VkImageViewType viewType);
VkImageView GetOrCreateSampledViewAtMipLevel(MG_State::GLState::ITextureObject& texture, Uint32 mipLevel); VkImageView GetOrCreateSampledViewAtMipLevel(MG_State::GLState::ITextureObject& texture, Uint32 mipLevel);
void UpdateTrackedImageLayout(MG_State::GLState::ITextureObject* texture, VkImageLayout newLayout); void UpdateTrackedImageLayout(MG_State::GLState::ITextureObject* texture, VkImageLayout newLayout);
void UpdateTrackedImageLayoutAfterAttachmentWrite(VkCommandBuffer commandBuffer, void UpdateTrackedImageLayoutAfterAttachmentWrite(VkCommandBuffer commandBuffer,
@@ -154,6 +211,7 @@ private:
Bool SyncTextureViews(const MG_State::GLState::ITextureObject& texture, TextureResource& resource); Bool SyncTextureViews(const MG_State::GLState::ITextureObject& texture, TextureResource& resource);
VkImageView CreateImageView(VkImage image, VkFormat format, VkImageAspectFlags aspect, VkImageView CreateImageView(VkImage image, VkFormat format, VkImageAspectFlags aspect,
VkImageViewType viewType, Uint32 baseMipLevel, Uint32 levelCount, VkImageViewType viewType, Uint32 baseMipLevel, Uint32 levelCount,
Uint32 baseArrayLayer,
Uint32 layerCount, Uint32 layerCount,
const VkComponentMapping* components = nullptr) const; const VkComponentMapping* components = nullptr) const;
Bool UploadDirtyMipLevels(MG_State::GLState::TextureObjectMipmap &mipmapTexture, Bool UploadDirtyMipLevels(MG_State::GLState::TextureObjectMipmap &mipmapTexture,
@@ -172,6 +230,9 @@ private:
void DeferViewRelease(VkImageView view); void DeferViewRelease(VkImageView view);
void CollectDeferredReleases(Uint32 frameIndex); void CollectDeferredReleases(Uint32 frameIndex);
void DestroyDeferredReleases(); void DestroyDeferredReleases();
static TextureIdentity MakeTextureIdentity(MG_State::GLState::ITextureObject* texture);
void EraseTrackedTexture(const TextureIdentity& identity);
void PruneStaleTextureAliases(MG_State::GLState::ITextureObject* texture);
VkDevice m_device = VK_NULL_HANDLE; VkDevice m_device = VK_NULL_HANDLE;
VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE; VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE;
@@ -181,8 +242,8 @@ private:
Uint32 m_currentFrameIndex = 0; Uint32 m_currentFrameIndex = 0;
Uint8 m_gcCounter = 0; Uint8 m_gcCounter = 0;
UnorderedMap<MG_State::GLState::ITextureObject*, WeakPtr<MG_State::GLState::ITextureObject>> m_aliveObjects; std::unordered_map<TextureIdentity, WeakPtr<MG_State::GLState::ITextureObject>, TextureIdentityHash> m_aliveObjects;
UnorderedMap<MG_State::GLState::ITextureObject*, TextureResource> m_textureResources; std::unordered_map<TextureIdentity, TextureResource, TextureIdentityHash> m_textureResources;
Vector<Vector<TextureResource>> m_deferredReleases; Vector<Vector<TextureResource>> m_deferredReleases;
Vector<Vector<VkImageView>> m_deferredViewReleases; Vector<Vector<VkImageView>> m_deferredViewReleases;
}; };
@@ -90,6 +90,78 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return requestedAlpha; return requestedAlpha;
} }
static void ApplyGLViewportState(VkCommandBuffer commandBuffer, const IntVec2& fallbackExtent) {
const IntVec4& viewportState = MG_State::pGLContext->GetViewport();
const FloatVec2& depthRange = MG_State::pGLContext->GetDepthRange();
VkViewport viewport{};
viewport.x = static_cast<float>(viewportState.x());
viewport.y = static_cast<float>(viewportState.y());
viewport.width =
static_cast<float>(viewportState.z() > 0 ? viewportState.z() : fallbackExtent.x());
viewport.height =
static_cast<float>(viewportState.w() > 0 ? viewportState.w() : fallbackExtent.y());
viewport.minDepth = depthRange.x();
viewport.maxDepth = depthRange.y();
vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
}
static void ApplyBlendConstants(VkCommandBuffer commandBuffer) {
const FloatVec4& blendColor = MG_State::pGLContext->GetBlendColor();
const float blendConstants[4] = {
blendColor.x(),
blendColor.y(),
blendColor.z(),
blendColor.w(),
};
vkCmdSetBlendConstants(commandBuffer, blendConstants);
}
static Bool DrawModeUsesPolygonFill(GLenum mode) {
switch (mode) {
case GL_TRIANGLES:
case GL_TRIANGLE_STRIP:
case GL_TRIANGLE_FAN:
return true;
default:
return false;
}
}
static void ApplyPolygonOffsetState(VkCommandBuffer commandBuffer) {
vkCmdSetDepthBias(commandBuffer, MG_State::pGLContext->GetPolygonOffsetUnits(), 0.0f,
MG_State::pGLContext->GetPolygonOffsetFactor());
}
static void ApplyLineWidthState(VkCommandBuffer commandBuffer) {
Float lineWidth = MG_State::pGLContext->GetLineWidth();
if (MG_Backend::pActiveBackendObject != nullptr) {
const auto& dynamicParameters = MG_Backend::pActiveBackendObject->GetDynamicParameters();
const Float minLineWidth = dynamicParameters.AliasedLineWidthRangeMin;
const Float maxLineWidth = dynamicParameters.AliasedLineWidthRangeMax;
if (lineWidth < minLineWidth) {
lineWidth = minLineWidth;
} else if (lineWidth > maxLineWidth) {
lineWidth = maxLineWidth;
}
}
vkCmdSetLineWidth(commandBuffer, lineWidth);
}
static void ApplyStencilState(VkCommandBuffer commandBuffer) {
const StencilFaceState& frontStencil = MG_State::pGLContext->GetStencilState(StencilFace::Front);
const StencilFaceState& backStencil = MG_State::pGLContext->GetStencilState(StencilFace::Back);
vkCmdSetStencilCompareMask(commandBuffer, VK_STENCIL_FACE_FRONT_BIT, frontStencil.ValueMask);
vkCmdSetStencilCompareMask(commandBuffer, VK_STENCIL_FACE_BACK_BIT, backStencil.ValueMask);
vkCmdSetStencilWriteMask(commandBuffer, VK_STENCIL_FACE_FRONT_BIT, frontStencil.WriteMask);
vkCmdSetStencilWriteMask(commandBuffer, VK_STENCIL_FACE_BACK_BIT, backStencil.WriteMask);
vkCmdSetStencilReference(commandBuffer, VK_STENCIL_FACE_FRONT_BIT,
static_cast<Uint32>(std::max(frontStencil.Ref, 0)));
vkCmdSetStencilReference(commandBuffer, VK_STENCIL_FACE_BACK_BIT,
static_cast<Uint32>(std::max(backStencil.Ref, 0)));
}
enum class NumericDomain { enum class NumericDomain {
Unknown, Unknown,
FloatLike, FloatLike,
@@ -617,7 +689,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
if (trackedAttachment.target != TrackedAttachmentTarget::Texture) { if (trackedAttachment.target != TrackedAttachmentTarget::Texture) {
continue; continue;
} }
if (trackedAttachment.texture == &texture) { const auto trackedTexture = trackedAttachment.texture.lock();
if (trackedTexture && trackedTexture.get() == &texture) {
return true; return true;
} }
} }
@@ -632,6 +705,51 @@ namespace MobileGL::MG_Backend::DirectVulkan {
MG_State::pGLContext->RecordError(code, MakeUnique<GenericErrorInfo>("DirectVulkan", func, message)); MG_State::pGLContext->RecordError(code, MakeUnique<GenericErrorInfo>("DirectVulkan", func, message));
} }
static Bool HasDistinctCompleteDepthStencilTextureAttachments(
const MG_State::GLState::FramebufferObject& framebufferObject) {
if (framebufferObject.GetExternalIndex() == 0) {
return false;
}
const auto& depthAttachment = framebufferObject.GetAttachment(FramebufferAttachmentType::Depth);
const auto& stencilAttachment = framebufferObject.GetAttachment(FramebufferAttachmentType::Stencil);
if (!depthAttachment.IsComplete() || !stencilAttachment.IsComplete() ||
!depthAttachment.IsTexture() || !stencilAttachment.IsTexture()) {
return false;
}
return depthAttachment.GetTexture().get() != stencilAttachment.GetTexture().get() ||
depthAttachment.GetTextureUploadTarget() != stencilAttachment.GetTextureUploadTarget() ||
depthAttachment.GetTextureLevel() != stencilAttachment.GetTextureLevel();
}
static Bool HasCompleteRenderbufferAttachment(const MG_State::GLState::FramebufferObject& framebufferObject) {
if (framebufferObject.GetExternalIndex() == 0) {
return false;
}
for (const auto& attachment : framebufferObject.GetAllAttachmentObjects()) {
if (attachment.IsRenderbuffer() && attachment.IsComplete()) {
return true;
}
}
return false;
}
static Bool IsUnsupportedFramebufferForDirectVulkan(
const MG_State::GLState::FramebufferObject& framebufferObject) {
return HasDistinctCompleteDepthStencilTextureAttachments(framebufferObject) ||
HasCompleteRenderbufferAttachment(framebufferObject);
}
static void RecordUnsupportedFramebufferError(const char* func) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidFramebufferOperation,
MakeUnique<GenericErrorInfo>(
"DirectVulkan", func,
"DirectVulkan does not support this non-default framebuffer configuration."));
}
static Bool IsValidSampledImageLayout(VkImageLayout layout) { static Bool IsValidSampledImageLayout(VkImageLayout layout) {
switch (layout) { switch (layout) {
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
@@ -778,6 +896,19 @@ void main() {
: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
} }
static Bool IsCubeMapFaceUploadTarget(TextureUploadTarget target) {
return target >= TextureUploadTarget::CubeMapPositiveX &&
target <= TextureUploadTarget::CubeMapNegativeZ;
}
static Uint32 ResolveAttachmentBaseArrayLayer(const MG_State::GLState::FramebufferAttachmentObject& attachment) {
const TextureUploadTarget uploadTarget = attachment.GetTextureUploadTarget();
if (!IsCubeMapFaceUploadTarget(uploadTarget)) {
return 0;
}
return static_cast<Uint32>(uploadTarget) - static_cast<Uint32>(TextureUploadTarget::CubeMapPositiveX);
}
enum class BlitSurfaceTransform : Uint32 { enum class BlitSurfaceTransform : Uint32 {
Identity = 0, Identity = 0,
Rotate90 = 1, Rotate90 = 1,
@@ -792,6 +923,8 @@ void main() {
IntVec2 extent = {0, 0}; IntVec2 extent = {0, 0};
Uint32 mipLevel = 0; Uint32 mipLevel = 0;
Uint32 mipLevelCount = 1; Uint32 mipLevelCount = 1;
Uint32 baseArrayLayer = 0;
Uint32 layerCount = 1;
const char* label = nullptr; const char* label = nullptr;
}; };
@@ -932,9 +1065,33 @@ void main() {
static Bool ResolveColorBlitBinding(MG_State::GLState::FramebufferObject& fbo, Bool isReadFramebuffer, static Bool ResolveColorBlitBinding(MG_State::GLState::FramebufferObject& fbo, Bool isReadFramebuffer,
Uint32 swapchainImageIndex, SwapchainObject& swapchainObject, Uint32 swapchainImageIndex, SwapchainObject& swapchainObject,
VkTextureManager& textureManager, BlitImageBinding& outBinding) { VkTextureManager& textureManager, BlitImageBinding& outBinding) {
const Bool isDefaultFbo = (&fbo == MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo->defaultFBO.get()); const Bool isDefaultFbo = fbo.IsDefaultFramebuffer();
const FramebufferAttachmentType attachmentType = const FramebufferAttachmentType attachmentType =
isReadFramebuffer ? fbo.GetReadBuffer() : fbo.GetDrawBuffers()[0]; isReadFramebuffer ? fbo.GetReadBuffer() : fbo.GetDrawBuffers()[0];
outBinding.label = isReadFramebuffer ? "read" : "draw";
if (isDefaultFbo) {
const Bool defaultColorAttachment =
attachmentType == FramebufferAttachmentType::Color0 ||
(attachmentType >= FramebufferAttachmentType::FrontLeft &&
attachmentType <= FramebufferAttachmentType::BackRight);
if (!defaultColorAttachment) {
MGLOG_E("BlitFramebuffer skipped: default framebuffer color attachment %d is not supported",
static_cast<Int>(attachmentType));
return false;
}
outBinding.image = swapchainObject.GetImage(swapchainImageIndex);
outBinding.trackedLayout = nullptr;
outBinding.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
const auto extent = swapchainObject.GetExtent();
outBinding.extent = {static_cast<Int>(extent.width), static_cast<Int>(extent.height)};
outBinding.mipLevel = 0;
outBinding.mipLevelCount = 1;
outBinding.baseArrayLayer = 0;
outBinding.layerCount = 1;
return true;
}
if (attachmentType < FramebufferAttachmentType::Color0 || attachmentType > FramebufferAttachmentType::Color31) { if (attachmentType < FramebufferAttachmentType::Color0 || attachmentType > FramebufferAttachmentType::Color31) {
MGLOG_E("BlitFramebuffer only supports color attachments right now (attachment=%d)", MGLOG_E("BlitFramebuffer only supports color attachments right now (attachment=%d)",
static_cast<Int>(attachmentType)); static_cast<Int>(attachmentType));
@@ -958,18 +1115,6 @@ void main() {
auto* texture = attachment.GetTexture().get(); auto* texture = attachment.GetTexture().get();
MOBILEGL_ASSERT(texture != nullptr, "ResolveColorBlitBinding: texture attachment is null"); MOBILEGL_ASSERT(texture != nullptr, "ResolveColorBlitBinding: texture attachment is null");
outBinding.label = isReadFramebuffer ? "read" : "draw";
if (isDefaultFbo) {
outBinding.image = swapchainObject.GetImage(swapchainImageIndex);
outBinding.trackedLayout = nullptr;
outBinding.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
const auto extent = swapchainObject.GetExtent();
outBinding.extent = {static_cast<Int>(extent.width), static_cast<Int>(extent.height)};
outBinding.mipLevel = 0;
outBinding.mipLevelCount = 1;
return true;
}
auto* resource = textureManager.SyncTextureAndGetDescriptor(*texture); auto* resource = textureManager.SyncTextureAndGetDescriptor(*texture);
if (resource == nullptr) { if (resource == nullptr) {
@@ -990,6 +1135,8 @@ void main() {
outBinding.extent = {attachmentExtent.x(), attachmentExtent.y()}; outBinding.extent = {attachmentExtent.x(), attachmentExtent.y()};
outBinding.mipLevel = static_cast<Uint32>(std::max(attachment.GetTextureLevel(), 0)); outBinding.mipLevel = static_cast<Uint32>(std::max(attachment.GetTextureLevel(), 0));
outBinding.mipLevelCount = resource->mipLevels; outBinding.mipLevelCount = resource->mipLevels;
outBinding.baseArrayLayer = ResolveAttachmentBaseArrayLayer(attachment);
outBinding.layerCount = 1;
return true; return true;
} }
@@ -998,8 +1145,7 @@ void main() {
VkTextureManager& textureManager, VkTextureManager& textureManager,
VkImageAspectFlags requiredAspectMask, VkImageAspectFlags requiredAspectMask,
BlitImageBinding& outBinding) { BlitImageBinding& outBinding) {
const Bool isDefaultFbo = const Bool isDefaultFbo = fbo.IsDefaultFramebuffer();
(&fbo == MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo->defaultFBO.get());
const auto attachmentType = ResolveFramebufferCopyAttachmentType(fbo, isReadFramebuffer, requiredAspectMask); const auto attachmentType = ResolveFramebufferCopyAttachmentType(fbo, isReadFramebuffer, requiredAspectMask);
if (attachmentType == FramebufferAttachmentType::None) { if (attachmentType == FramebufferAttachmentType::None) {
MGLOG_E("BlitFramebuffer skipped: unsupported aspect mask=0x%x", MGLOG_E("BlitFramebuffer skipped: unsupported aspect mask=0x%x",
@@ -1013,6 +1159,8 @@ void main() {
outBinding.extent = {static_cast<Int>(extent.width), static_cast<Int>(extent.height)}; outBinding.extent = {static_cast<Int>(extent.width), static_cast<Int>(extent.height)};
outBinding.mipLevel = 0; outBinding.mipLevel = 0;
outBinding.mipLevelCount = 1; outBinding.mipLevelCount = 1;
outBinding.baseArrayLayer = 0;
outBinding.layerCount = 1;
outBinding.trackedLayout = nullptr; outBinding.trackedLayout = nullptr;
if ((requiredAspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != 0) { if ((requiredAspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != 0) {
outBinding.image = swapchainObject.GetImage(swapchainImageIndex); outBinding.image = swapchainObject.GetImage(swapchainImageIndex);
@@ -1067,6 +1215,8 @@ void main() {
outBinding.extent = {attachmentExtent.x(), attachmentExtent.y()}; outBinding.extent = {attachmentExtent.x(), attachmentExtent.y()};
outBinding.mipLevel = static_cast<Uint32>(std::max(attachment.GetTextureLevel(), 0)); outBinding.mipLevel = static_cast<Uint32>(std::max(attachment.GetTextureLevel(), 0));
outBinding.mipLevelCount = resource->mipLevels; outBinding.mipLevelCount = resource->mipLevels;
outBinding.baseArrayLayer = ResolveAttachmentBaseArrayLayer(attachment);
outBinding.layerCount = 1;
return true; return true;
} }
@@ -1099,6 +1249,8 @@ void main() {
static_cast<Int>(std::max(1u, resource->extent.height >> mipLevel))}; static_cast<Int>(std::max(1u, resource->extent.height >> mipLevel))};
outBinding.mipLevel = mipLevel; outBinding.mipLevel = mipLevel;
outBinding.mipLevelCount = 1; outBinding.mipLevelCount = 1;
outBinding.baseArrayLayer = 0;
outBinding.layerCount = 1;
outBinding.label = "destination texture"; outBinding.label = "destination texture";
return true; return true;
} }
@@ -1108,8 +1260,7 @@ void main() {
VkTextureManager& textureManager, VkTextureManager& textureManager,
VkImageAspectFlags requiredAspectMask, VkImageAspectFlags requiredAspectMask,
BlitImageBinding& outBinding) { BlitImageBinding& outBinding) {
const Bool isDefaultFbo = const Bool isDefaultFbo = fbo.IsDefaultFramebuffer();
(&fbo == MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo->defaultFBO.get());
const auto attachmentType = ResolveFramebufferCopyAttachmentType(fbo, true, requiredAspectMask); const auto attachmentType = ResolveFramebufferCopyAttachmentType(fbo, true, requiredAspectMask);
if (attachmentType == FramebufferAttachmentType::None) { if (attachmentType == FramebufferAttachmentType::None) {
MGLOG_E("CopyTexSubImage2D skipped: unsupported source aspect mask=0x%x", MGLOG_E("CopyTexSubImage2D skipped: unsupported source aspect mask=0x%x",
@@ -1123,6 +1274,8 @@ void main() {
outBinding.extent = {static_cast<Int>(extent.width), static_cast<Int>(extent.height)}; outBinding.extent = {static_cast<Int>(extent.width), static_cast<Int>(extent.height)};
outBinding.mipLevel = 0; outBinding.mipLevel = 0;
outBinding.mipLevelCount = 1; outBinding.mipLevelCount = 1;
outBinding.baseArrayLayer = 0;
outBinding.layerCount = 1;
outBinding.trackedLayout = nullptr; outBinding.trackedLayout = nullptr;
if ((requiredAspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != 0) { if ((requiredAspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != 0) {
outBinding.image = swapchainObject.GetImage(swapchainImageIndex); outBinding.image = swapchainObject.GetImage(swapchainImageIndex);
@@ -1179,6 +1332,8 @@ void main() {
outBinding.extent = {attachmentExtent.x(), attachmentExtent.y()}; outBinding.extent = {attachmentExtent.x(), attachmentExtent.y()};
outBinding.mipLevel = static_cast<Uint32>(std::max(attachment.GetTextureLevel(), 0)); outBinding.mipLevel = static_cast<Uint32>(std::max(attachment.GetTextureLevel(), 0));
outBinding.mipLevelCount = 1; outBinding.mipLevelCount = 1;
outBinding.baseArrayLayer = ResolveAttachmentBaseArrayLayer(attachment);
outBinding.layerCount = 1;
return true; return true;
} }
@@ -1399,7 +1554,7 @@ void main() {
ProgramFactory::CompileOptionFlags flags = ProgramFactory::CompileOptionBit::PositionZRemap; ProgramFactory::CompileOptionFlags flags = ProgramFactory::CompileOptionBit::PositionZRemap;
const auto& currentDrawFBO = const auto& currentDrawFBO =
MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject(); MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
if (currentDrawFBO == MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo->defaultFBO) { if (currentDrawFBO != nullptr && currentDrawFBO->IsDefaultFramebuffer()) {
flags |= ProgramFactory::CompileOptionBit::PositionYFlip; flags |= ProgramFactory::CompileOptionBit::PositionYFlip;
switch (preTransform) { switch (preTransform) {
case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR: case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
@@ -2021,6 +2176,7 @@ void main() {
.pipelineLayout = programObj.pipelineLayout, .pipelineLayout = programObj.pipelineLayout,
.renderPass = renderPassEntry.renderPass, .renderPass = renderPassEntry.renderPass,
.colorAttachmentCount = renderPassEntry.colorAttachmentCount, .colorAttachmentCount = renderPassEntry.colorAttachmentCount,
.rasterizationSamples = renderPassEntry.sampleCount,
.subpass = 0, .subpass = 0,
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
.cullMode = VK_CULL_MODE_NONE, .cullMode = VK_CULL_MODE_NONE,
@@ -2292,14 +2448,7 @@ void main() {
vkCmdBeginRenderPass(frame.commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); vkCmdBeginRenderPass(frame.commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
VkViewport viewport{}; ApplyGLViewportState(frame.commandBuffer, dstTexelSize.xy());
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = static_cast<float>(dstTexelSize.x());
viewport.height = static_cast<float>(dstTexelSize.y());
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
vkCmdSetViewport(frame.commandBuffer, 0, 1, &viewport);
VkRect2D scissor{}; VkRect2D scissor{};
scissor.offset = {0, 0}; scissor.offset = {0, 0};
@@ -2471,6 +2620,16 @@ void main() {
} }
auto cullFaceEnabled = MG_State::pGLContext->IsCapabilityEnabled(CapabilityInput::CullFace); auto cullFaceEnabled = MG_State::pGLContext->IsCapabilityEnabled(CapabilityInput::CullFace);
auto depthTestEnabled = MG_State::pGLContext->IsCapabilityEnabled(CapabilityInput::DepthTest); auto depthTestEnabled = MG_State::pGLContext->IsCapabilityEnabled(CapabilityInput::DepthTest);
auto polygonOffsetFillEnabled =
MG_State::pGLContext->IsCapabilityEnabled(CapabilityInput::PolygonOffsetFill) &&
DrawModeUsesPolygonFill(mode);
auto rasterizerDiscardEnabled =
MG_State::pGLContext->IsCapabilityEnabled(CapabilityInput::RasterizerDiscard);
auto colorLogicOpEnabled =
MG_State::pGLContext->IsCapabilityEnabled(CapabilityInput::ColorLogicOp) && m_logicOpFeatureEnabled;
auto stencilTestEnabled = MG_State::pGLContext->IsCapabilityEnabled(CapabilityInput::StencilTest);
const StencilFaceState& frontStencil = MG_State::pGLContext->GetStencilState(StencilFace::Front);
const StencilFaceState& backStencil = MG_State::pGLContext->GetStencilState(StencilFace::Back);
auto mask = MG_State::pGLContext->GetColorMask(); auto mask = MG_State::pGLContext->GetColorMask();
const auto colorWriteMask = static_cast<VkColorComponentFlags>( const auto colorWriteMask = static_cast<VkColorComponentFlags>(
(mask.r() ? VK_COLOR_COMPONENT_R_BIT : 0u) | (mask.r() ? VK_COLOR_COMPONENT_R_BIT : 0u) |
@@ -2484,6 +2643,7 @@ void main() {
.pipelineLayout = programObj.pipelineLayout, .pipelineLayout = programObj.pipelineLayout,
.renderPass = renderPassEntry.renderPass, .renderPass = renderPassEntry.renderPass,
.colorAttachmentCount = renderPassEntry.colorAttachmentCount, .colorAttachmentCount = renderPassEntry.colorAttachmentCount,
.rasterizationSamples = renderPassEntry.sampleCount,
.subpass = 0, .subpass = 0,
.topology = MG_Util::ConvertPrimitiveModeToVkEnum(mode), .topology = MG_Util::ConvertPrimitiveModeToVkEnum(mode),
.cullMode = cullFaceEnabled .cullMode = cullFaceEnabled
@@ -2492,19 +2652,52 @@ void main() {
.frontFace = VK_FRONT_FACE_CLOCKWISE, .frontFace = VK_FRONT_FACE_CLOCKWISE,
.depthTestEnable = depthTestEnabled, .depthTestEnable = depthTestEnabled,
.depthWriteEnable = depthTestEnabled && MG_State::pGLContext->GetDepthMask(), .depthWriteEnable = depthTestEnabled && MG_State::pGLContext->GetDepthMask(),
.depthBiasEnable = polygonOffsetFillEnabled,
.rasterizerDiscardEnable = rasterizerDiscardEnabled,
.logicOpEnable = colorLogicOpEnabled,
.stencilTestEnable = stencilTestEnabled,
.depthCompareOp = MG_Util::ConvertDepthTestFuncToVkEnum(MG_State::pGLContext->GetDepthFunc()), .depthCompareOp = MG_Util::ConvertDepthTestFuncToVkEnum(MG_State::pGLContext->GetDepthFunc()),
.logicOp = MG_Util::ConvertLogicOperationToVkEnum(MG_State::pGLContext->GetLogicOp()),
.frontStencilFailOp = MG_Util::ConvertStencilOperationToVkEnum(frontStencil.FailOp),
.frontStencilPassOp = MG_Util::ConvertStencilOperationToVkEnum(frontStencil.PassDepthPassOp),
.frontStencilDepthFailOp = MG_Util::ConvertStencilOperationToVkEnum(frontStencil.PassDepthFailOp),
.frontStencilCompareOp = MG_Util::ConvertDepthTestFuncToVkEnum(frontStencil.Func),
.backStencilFailOp = MG_Util::ConvertStencilOperationToVkEnum(backStencil.FailOp),
.backStencilPassOp = MG_Util::ConvertStencilOperationToVkEnum(backStencil.PassDepthPassOp),
.backStencilDepthFailOp = MG_Util::ConvertStencilOperationToVkEnum(backStencil.PassDepthFailOp),
.backStencilCompareOp = MG_Util::ConvertDepthTestFuncToVkEnum(backStencil.Func),
.stages = &programObj.stages, .stages = &programObj.stages,
.vertexInputState = pipelineVertexInputState .vertexInputState = pipelineVertexInputState
}; };
if (!payload.stencilTestEnable) {
payload.frontStencilFailOp = VK_STENCIL_OP_KEEP;
payload.frontStencilPassOp = VK_STENCIL_OP_KEEP;
payload.frontStencilDepthFailOp = VK_STENCIL_OP_KEEP;
payload.frontStencilCompareOp = VK_COMPARE_OP_ALWAYS;
payload.backStencilFailOp = VK_STENCIL_OP_KEEP;
payload.backStencilPassOp = VK_STENCIL_OP_KEEP;
payload.backStencilDepthFailOp = VK_STENCIL_OP_KEEP;
payload.backStencilCompareOp = VK_COMPARE_OP_ALWAYS;
}
const Bool hasDepthStencilAttachment = renderPassEntry.hasDepthStencilAttachment; const Bool hasDepthStencilAttachment = renderPassEntry.hasDepthStencilAttachment;
if (!hasDepthStencilAttachment && (payload.depthTestEnable || payload.depthWriteEnable)) { if (!hasDepthStencilAttachment &&
MGLOG_D("GetOrCreatePipeline: disabling depth test/write for program=%u because render pass has no depth attachment (attachmentCount=%u colorAttachmentCount=%u)", (payload.depthTestEnable || payload.depthWriteEnable || payload.stencilTestEnable)) {
MGLOG_D("GetOrCreatePipeline: disabling depth/stencil tests for program=%u because render pass has no depth attachment (attachmentCount=%u colorAttachmentCount=%u)",
program.GetExternalIndex(), program.GetExternalIndex(),
renderPassEntry.attachmentCount, renderPassEntry.attachmentCount,
renderPassEntry.colorAttachmentCount); renderPassEntry.colorAttachmentCount);
payload.depthTestEnable = false; payload.depthTestEnable = false;
payload.depthWriteEnable = false; payload.depthWriteEnable = false;
payload.stencilTestEnable = false;
payload.depthCompareOp = VK_COMPARE_OP_ALWAYS; payload.depthCompareOp = VK_COMPARE_OP_ALWAYS;
payload.frontStencilFailOp = VK_STENCIL_OP_KEEP;
payload.frontStencilPassOp = VK_STENCIL_OP_KEEP;
payload.frontStencilDepthFailOp = VK_STENCIL_OP_KEEP;
payload.frontStencilCompareOp = VK_COMPARE_OP_ALWAYS;
payload.backStencilFailOp = VK_STENCIL_OP_KEEP;
payload.backStencilPassOp = VK_STENCIL_OP_KEEP;
payload.backStencilDepthFailOp = VK_STENCIL_OP_KEEP;
payload.backStencilCompareOp = VK_COMPARE_OP_ALWAYS;
} }
const Uint32 fragmentOutputMask = programObj.activeFragmentOutputLocationMask; const Uint32 fragmentOutputMask = programObj.activeFragmentOutputLocationMask;
MOBILEGL_ASSERT( MOBILEGL_ASSERT(
@@ -2519,8 +2712,7 @@ void main() {
const auto& drawFboBinding = const auto& drawFboBinding =
MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject(); MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
MOBILEGL_ASSERT(drawFboBinding != nullptr, "GetOrCreatePipeline: draw framebuffer is null"); MOBILEGL_ASSERT(drawFboBinding != nullptr, "GetOrCreatePipeline: draw framebuffer is null");
const Bool isDefaultDrawFbo = const Bool isDefaultDrawFbo = drawFboBinding->IsDefaultFramebuffer();
drawFboBinding.get() == MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo->defaultFBO.get();
const auto& drawBuffers = drawFboBinding->GetDrawBuffers(); const auto& drawBuffers = drawFboBinding->GetDrawBuffers();
auto resolveCompleteColorAttachmentTexture = [&](Uint32 drawBufferIndex) -> MG_State::GLState::ITextureObject* { auto resolveCompleteColorAttachmentTexture = [&](Uint32 drawBufferIndex) -> MG_State::GLState::ITextureObject* {
if (isDefaultDrawFbo || drawBufferIndex >= drawBuffers.size()) { if (isDefaultDrawFbo || drawBufferIndex >= drawBuffers.size()) {
@@ -2681,6 +2873,10 @@ void main() {
m_textureManager->CollectGarbage(); m_textureManager->CollectGarbage();
const auto& drawFbo = const auto& drawFbo =
MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject(); MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
if (drawFbo != nullptr && IsUnsupportedFramebufferForDirectVulkan(*drawFbo)) {
RecordUnsupportedFramebufferError(__func__);
return false;
}
const auto& vao = *MG_State::pGLContext->GetBoundVertexArray(); const auto& vao = *MG_State::pGLContext->GetBoundVertexArray();
const auto& program = *MG_State::pGLContext->GetCurrentProgram(); const auto& program = *MG_State::pGLContext->GetCurrentProgram();
ProgramFactory::CompileOptionFlags transformFlags = GetShaderTransformFlags(m_swapchainObject.GetPreTransform()); ProgramFactory::CompileOptionFlags transformFlags = GetShaderTransformFlags(m_swapchainObject.GetPreTransform());
@@ -2812,14 +3008,11 @@ void main() {
MOBILEGL_ASSERT(idxUploadOk, "SetupDraw skipped: failed to upload index buffer"); MOBILEGL_ASSERT(idxUploadOk, "SetupDraw skipped: failed to upload index buffer");
} }
VkViewport viewport{}; ApplyGLViewportState(frame.commandBuffer, renderPassEntry->extent);
viewport.x = 0.0f; ApplyBlendConstants(frame.commandBuffer);
viewport.y = 0.0f; ApplyPolygonOffsetState(frame.commandBuffer);
viewport.width = static_cast<float>(renderPassEntry->extent.x()); ApplyLineWidthState(frame.commandBuffer);
viewport.height = static_cast<float>(renderPassEntry->extent.y()); ApplyStencilState(frame.commandBuffer);
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
vkCmdSetViewport(frame.commandBuffer, 0, 1, &viewport);
Bool scissorEnabled = MG_State::pGLContext->IsCapabilityEnabled(CapabilityInput::ScissorTest); Bool scissorEnabled = MG_State::pGLContext->IsCapabilityEnabled(CapabilityInput::ScissorTest);
VkRect2D scissor{}; VkRect2D scissor{};
@@ -2964,6 +3157,10 @@ void main() {
m_clearManager->CollectGarbage(); m_clearManager->CollectGarbage();
auto* fbo = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject().get(); auto* fbo = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject().get();
MOBILEGL_ASSERT(fbo, "VulkanRenderer::Clear: draw framebuffer not found (fbo == nullptr)"); MOBILEGL_ASSERT(fbo, "VulkanRenderer::Clear: draw framebuffer not found (fbo == nullptr)");
if (IsUnsupportedFramebufferForDirectVulkan(*fbo)) {
RecordUnsupportedFramebufferError(__func__);
return;
}
ClearFramebufferPayload payload { ClearFramebufferPayload payload {
.color = MG_State::pGLContext->GetClearColor(), .color = MG_State::pGLContext->GetClearColor(),
@@ -2977,6 +3174,10 @@ void main() {
const MG_State::GLState::FramebufferObject& framebuffer, GLenum buffer, GLint drawbuffer, const MG_State::GLState::FramebufferObject& framebuffer, GLenum buffer, GLint drawbuffer,
const ClearAttachmentPayload& clearPayload) { const ClearAttachmentPayload& clearPayload) {
m_clearManager->CollectGarbage(); m_clearManager->CollectGarbage();
if (IsUnsupportedFramebufferForDirectVulkan(framebuffer)) {
RecordUnsupportedFramebufferError(__func__);
return;
}
auto queueAttachmentClear = [&](FramebufferAttachmentType attachmentType) { auto queueAttachmentClear = [&](FramebufferAttachmentType attachmentType) {
if (attachmentType == FramebufferAttachmentType::None) { if (attachmentType == FramebufferAttachmentType::None) {
@@ -2986,11 +3187,7 @@ void main() {
if (!attachment.IsTexture() || attachment.IsRenderbuffer()) { if (!attachment.IsTexture() || attachment.IsRenderbuffer()) {
return; return;
} }
auto texture = attachment.GetTexture(); m_clearManager->QueueClear(clearPayload, attachment);
if (!texture) {
return;
}
m_clearManager->QueueClear(clearPayload, texture);
}; };
switch (buffer) { switch (buffer) {
@@ -3145,8 +3342,8 @@ void main() {
Bool VulkanRenderer::MaterializePendingClearForTexture(VkCommandBuffer commandBuffer, Bool VulkanRenderer::MaterializePendingClearForTexture(VkCommandBuffer commandBuffer,
MG_State::GLState::ITextureObject& texture) { MG_State::GLState::ITextureObject& texture) {
ClearAttachmentPayload clearPayload{}; Vector<PendingClearEntry> pendingClears;
if (!m_clearManager->GetPendingClear(&texture, clearPayload)) { if (!m_clearManager->GetPendingClears(&texture, pendingClears)) {
return true; return true;
} }
MOBILEGL_ASSERT(VkRenderPassManager::GetActiveRenderPass() == nullptr, MOBILEGL_ASSERT(VkRenderPassManager::GetActiveRenderPass() == nullptr,
@@ -3165,18 +3362,28 @@ void main() {
Bool ok = VkTextureManager::TransitionImageLayout( Bool ok = VkTextureManager::TransitionImageLayout(
commandBuffer, resource->image, resource->layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, commandBuffer, resource->image, resource->layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
srcStageMask, VK_PIPELINE_STAGE_TRANSFER_BIT, srcAccessMask, VK_ACCESS_TRANSFER_WRITE_BIT, srcStageMask, VK_PIPELINE_STAGE_TRANSFER_BIT, srcAccessMask, VK_ACCESS_TRANSFER_WRITE_BIT,
resource->aspect, 0, resource->mipLevels); resource->aspect, 0, resource->mipLevels, resource->arrayLayers);
MOBILEGL_ASSERT(ok, MOBILEGL_ASSERT(ok,
"MaterializePendingClearForTexture: failed to transition textureId=%d to TRANSFER_DST", "MaterializePendingClearForTexture: failed to transition textureId=%d to TRANSFER_DST",
texture.GetExternalIndex()); texture.GetExternalIndex());
VkImageSubresourceRange subresourceRange{};
subresourceRange.baseMipLevel = 0;
subresourceRange.levelCount = 1;
subresourceRange.baseArrayLayer = 0;
subresourceRange.layerCount = 1;
VkImageLayout sampledLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; VkImageLayout sampledLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
for (const auto& pendingClear : pendingClears) {
MOBILEGL_ASSERT(pendingClear.key.mipLevel < resource->mipLevels,
"MaterializePendingClearForTexture: textureId=%d pending clear mip=%u out of range %u",
texture.GetExternalIndex(), pendingClear.key.mipLevel, resource->mipLevels);
MOBILEGL_ASSERT(pendingClear.key.baseArrayLayer + pendingClear.key.layerCount <= resource->arrayLayers,
"MaterializePendingClearForTexture: textureId=%d pending clear layer span [%u, %u) exceeds arrayLayers=%u",
texture.GetExternalIndex(), pendingClear.key.baseArrayLayer,
pendingClear.key.baseArrayLayer + pendingClear.key.layerCount, resource->arrayLayers);
VkImageSubresourceRange subresourceRange{};
subresourceRange.baseMipLevel = pendingClear.key.mipLevel;
subresourceRange.levelCount = 1;
subresourceRange.baseArrayLayer = pendingClear.key.baseArrayLayer;
subresourceRange.layerCount = pendingClear.key.layerCount;
const auto& clearPayload = pendingClear.payload;
if ((resource->aspect & VK_IMAGE_ASPECT_COLOR_BIT) != 0) { if ((resource->aspect & VK_IMAGE_ASPECT_COLOR_BIT) != 0) {
subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
VkClearColorValue clearValue{}; VkClearColorValue clearValue{};
@@ -3207,11 +3414,13 @@ void main() {
&clearValue, 1, &subresourceRange); &clearValue, 1, &subresourceRange);
sampledLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; sampledLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
} }
}
ok = VkTextureManager::TransitionImageLayout( ok = VkTextureManager::TransitionImageLayout(
commandBuffer, resource->image, clearLayout, sampledLayout, commandBuffer, resource->image, clearLayout, sampledLayout,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, resource->aspect, 0, resource->mipLevels); VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, resource->aspect, 0, resource->mipLevels,
resource->arrayLayers);
MOBILEGL_ASSERT(ok, MOBILEGL_ASSERT(ok,
"MaterializePendingClearForTexture: failed to transition textureId=%d to sampled layout", "MaterializePendingClearForTexture: failed to transition textureId=%d to sampled layout",
texture.GetExternalIndex()); texture.GetExternalIndex());
@@ -3229,8 +3438,7 @@ void main() {
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLenum filter) { GLenum filter) {
const Bool drawIsDefaultFbo = const Bool drawIsDefaultFbo = drawFbo.IsDefaultFramebuffer();
(&drawFbo == MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo->defaultFBO.get());
if (!drawIsDefaultFbo) { if (!drawIsDefaultFbo) {
return false; return false;
} }
@@ -3279,14 +3487,7 @@ void main() {
const Bool ok = VkRenderPassManager::BeginRenderPass(frame.commandBuffer, renderPassEntry); const Bool ok = VkRenderPassManager::BeginRenderPass(frame.commandBuffer, renderPassEntry);
MOBILEGL_ASSERT(ok, "%s: BeginRenderPass failed", __func__); MOBILEGL_ASSERT(ok, "%s: BeginRenderPass failed", __func__);
VkViewport viewport{}; ApplyGLViewportState(frame.commandBuffer, renderPassEntry.extent);
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = static_cast<float>(renderPassEntry.extent.x());
viewport.height = static_cast<float>(renderPassEntry.extent.y());
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
vkCmdSetViewport(frame.commandBuffer, 0, 1, &viewport);
VkRect2D scissor{}; VkRect2D scissor{};
scissor.offset = {0, 0}; scissor.offset = {0, 0};
@@ -3396,6 +3597,11 @@ void main() {
MOBILEGL_ASSERT(readFbo != nullptr, "VulkanRenderer::BlitFramebuffer: read framebuffer is null"); MOBILEGL_ASSERT(readFbo != nullptr, "VulkanRenderer::BlitFramebuffer: read framebuffer is null");
MOBILEGL_ASSERT(drawFbo != nullptr, "VulkanRenderer::BlitFramebuffer: draw framebuffer is null"); MOBILEGL_ASSERT(drawFbo != nullptr, "VulkanRenderer::BlitFramebuffer: draw framebuffer is null");
if (IsUnsupportedFramebufferForDirectVulkan(*readFbo) ||
IsUnsupportedFramebufferForDirectVulkan(*drawFbo)) {
RecordUnsupportedFramebufferError(__func__);
return;
}
auto& frame = m_frameContext.GetCurrent(); auto& frame = m_frameContext.GetCurrent();
if (!frame.isCommandRecording) { if (!frame.isCommandRecording) {
@@ -3408,10 +3614,8 @@ void main() {
VkRenderPassManager::EndRenderPass(frame.commandBuffer); VkRenderPassManager::EndRenderPass(frame.commandBuffer);
} }
const Bool readIsDefaultFbo = const Bool readIsDefaultFbo = readFbo->IsDefaultFramebuffer();
(readFbo == MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo->defaultFBO); const Bool drawIsDefaultFbo = drawFbo->IsDefaultFramebuffer();
const Bool drawIsDefaultFbo =
(drawFbo == MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo->defaultFBO);
if (isColorBlit && drawIsDefaultFbo && if (isColorBlit && drawIsDefaultFbo &&
RequiresShaderBlitToDefaultFramebuffer(m_swapchainObject.GetPreTransform())) { RequiresShaderBlitToDefaultFramebuffer(m_swapchainObject.GetPreTransform())) {
if (TryBlitToDefaultFramebufferWithShader(frame, *readFbo, *drawFbo, if (TryBlitToDefaultFramebufferWithShader(frame, *readFbo, *drawFbo,
@@ -3518,13 +3722,13 @@ void main() {
VkImageCopy copyRegion{}; VkImageCopy copyRegion{};
copyRegion.srcSubresource.aspectMask = srcBinding.aspectMask; copyRegion.srcSubresource.aspectMask = srcBinding.aspectMask;
copyRegion.srcSubresource.mipLevel = srcBinding.mipLevel; copyRegion.srcSubresource.mipLevel = srcBinding.mipLevel;
copyRegion.srcSubresource.baseArrayLayer = 0; copyRegion.srcSubresource.baseArrayLayer = srcBinding.baseArrayLayer;
copyRegion.srcSubresource.layerCount = 1; copyRegion.srcSubresource.layerCount = srcBinding.layerCount;
copyRegion.srcOffset = {srcX0, srcY0, 0}; copyRegion.srcOffset = {srcX0, srcY0, 0};
copyRegion.dstSubresource.aspectMask = dstBinding.aspectMask; copyRegion.dstSubresource.aspectMask = dstBinding.aspectMask;
copyRegion.dstSubresource.mipLevel = dstBinding.mipLevel; copyRegion.dstSubresource.mipLevel = dstBinding.mipLevel;
copyRegion.dstSubresource.baseArrayLayer = 0; copyRegion.dstSubresource.baseArrayLayer = dstBinding.baseArrayLayer;
copyRegion.dstSubresource.layerCount = 1; copyRegion.dstSubresource.layerCount = dstBinding.layerCount;
copyRegion.dstOffset = {dstX0, dstY0, 0}; copyRegion.dstOffset = {dstX0, dstY0, 0};
copyRegion.extent = {static_cast<Uint32>(srcWidth), static_cast<Uint32>(srcHeight), 1}; copyRegion.extent = {static_cast<Uint32>(srcWidth), static_cast<Uint32>(srcHeight), 1};
@@ -3654,14 +3858,14 @@ void main() {
VkImageBlit blitRegion{}; VkImageBlit blitRegion{};
blitRegion.srcSubresource.aspectMask = srcBinding.aspectMask; blitRegion.srcSubresource.aspectMask = srcBinding.aspectMask;
blitRegion.srcSubresource.mipLevel = srcBinding.mipLevel; blitRegion.srcSubresource.mipLevel = srcBinding.mipLevel;
blitRegion.srcSubresource.baseArrayLayer = 0; blitRegion.srcSubresource.baseArrayLayer = srcBinding.baseArrayLayer;
blitRegion.srcSubresource.layerCount = 1; blitRegion.srcSubresource.layerCount = srcBinding.layerCount;
blitRegion.srcOffsets[0] = {srcX0, srcY0, 0}; blitRegion.srcOffsets[0] = {srcX0, srcY0, 0};
blitRegion.srcOffsets[1] = {srcX1, srcY1, 1}; blitRegion.srcOffsets[1] = {srcX1, srcY1, 1};
blitRegion.dstSubresource.aspectMask = dstBinding.aspectMask; blitRegion.dstSubresource.aspectMask = dstBinding.aspectMask;
blitRegion.dstSubresource.mipLevel = dstBinding.mipLevel; blitRegion.dstSubresource.mipLevel = dstBinding.mipLevel;
blitRegion.dstSubresource.baseArrayLayer = 0; blitRegion.dstSubresource.baseArrayLayer = dstBinding.baseArrayLayer;
blitRegion.dstSubresource.layerCount = 1; blitRegion.dstSubresource.layerCount = dstBinding.layerCount;
blitRegion.dstOffsets[0] = {dstX0, dstY0, 0}; blitRegion.dstOffsets[0] = {dstX0, dstY0, 0};
blitRegion.dstOffsets[1] = {dstX1, dstY1, 1}; blitRegion.dstOffsets[1] = {dstX1, dstY1, 1};
if (drawIsDefaultFbo) { if (drawIsDefaultFbo) {
@@ -3744,6 +3948,11 @@ void main() {
"CopyTexSubImage2D requires a framebuffer bound to GL_READ_FRAMEBUFFER."); "CopyTexSubImage2D requires a framebuffer bound to GL_READ_FRAMEBUFFER.");
return; return;
} }
if (IsUnsupportedFramebufferForDirectVulkan(*readFbo)) {
RecordTextureCopyError(__func__, ErrorCode::InvalidFramebufferOperation,
"CopyTexSubImage2D does not support the current non-default read framebuffer configuration on DirectVulkan.");
return;
}
auto& frame = m_frameContext.GetCurrent(); auto& frame = m_frameContext.GetCurrent();
if (!frame.isCommandRecording) { if (!frame.isCommandRecording) {
@@ -3755,8 +3964,7 @@ void main() {
VkRenderPassManager::EndRenderPass(frame.commandBuffer); VkRenderPassManager::EndRenderPass(frame.commandBuffer);
} }
const Bool readIsDefaultFbo = const Bool readIsDefaultFbo = readFbo->IsDefaultFramebuffer();
(readFbo == MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo->defaultFBO);
BlitImageBinding dstBinding{}; BlitImageBinding dstBinding{};
if (!ResolveTextureCopyDestinationBinding(*destinationTexture, static_cast<Uint32>(level), *m_textureManager, if (!ResolveTextureCopyDestinationBinding(*destinationTexture, static_cast<Uint32>(level), *m_textureManager,
@@ -3842,13 +4050,13 @@ void main() {
VkImageCopy copyRegion{}; VkImageCopy copyRegion{};
copyRegion.srcSubresource.aspectMask = srcBinding.aspectMask; copyRegion.srcSubresource.aspectMask = srcBinding.aspectMask;
copyRegion.srcSubresource.mipLevel = srcBinding.mipLevel; copyRegion.srcSubresource.mipLevel = srcBinding.mipLevel;
copyRegion.srcSubresource.baseArrayLayer = 0; copyRegion.srcSubresource.baseArrayLayer = srcBinding.baseArrayLayer;
copyRegion.srcSubresource.layerCount = 1; copyRegion.srcSubresource.layerCount = srcBinding.layerCount;
copyRegion.srcOffset = {x, y, 0}; copyRegion.srcOffset = {x, y, 0};
copyRegion.dstSubresource.aspectMask = dstBinding.aspectMask; copyRegion.dstSubresource.aspectMask = dstBinding.aspectMask;
copyRegion.dstSubresource.mipLevel = dstBinding.mipLevel; copyRegion.dstSubresource.mipLevel = dstBinding.mipLevel;
copyRegion.dstSubresource.baseArrayLayer = 0; copyRegion.dstSubresource.baseArrayLayer = dstBinding.baseArrayLayer;
copyRegion.dstSubresource.layerCount = 1; copyRegion.dstSubresource.layerCount = dstBinding.layerCount;
copyRegion.dstOffset = {xoffset, yoffset, 0}; copyRegion.dstOffset = {xoffset, yoffset, 0};
copyRegion.extent = {static_cast<Uint32>(width), static_cast<Uint32>(height), 1}; copyRegion.extent = {static_cast<Uint32>(width), static_cast<Uint32>(height), 1};
vkCmdCopyImage(frame.commandBuffer, vkCmdCopyImage(frame.commandBuffer,
@@ -3957,8 +4165,7 @@ void main() {
VkRenderPassManager::EndRenderPass(frame.commandBuffer); VkRenderPassManager::EndRenderPass(frame.commandBuffer);
} }
const Bool readIsDefaultFbo = const Bool readIsDefaultFbo = readFbo->IsDefaultFramebuffer();
(readFbo == MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo->defaultFBO);
BlitImageBinding srcBinding{}; BlitImageBinding srcBinding{};
if (!ResolveColorBlitBinding(*readFbo, true, m_imageIndexAcquired, m_swapchainObject, *m_textureManager, if (!ResolveColorBlitBinding(*readFbo, true, m_imageIndexAcquired, m_swapchainObject, *m_textureManager,
srcBinding)) { srcBinding)) {
@@ -4688,7 +4895,8 @@ void main() {
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) { if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {
MGLOG_D("Present, vkAcquireNextImageKHR got %d, recreating swapchain", result); MGLOG_D("Present, vkAcquireNextImageKHR got %d, recreating swapchain", result);
RecreateSwapchain(); RecreateSwapchain();
result = VK_SUCCESS; result =
m_frameContext.WaitAndAcquireNextImage(m_device, m_swapchainObject.GetHandle(), m_imageIndexAcquired);
} }
VK_VERIFY(result, "Present, vkAcquireNextImageKHR"); VK_VERIFY(result, "Present, vkAcquireNextImageKHR");
CollectDeferredDepthMipmapCleanup(m_frameContext.GetCurrentFrameIndex()); CollectDeferredDepthMipmapCleanup(m_frameContext.GetCurrentFrameIndex());
@@ -4974,10 +5182,14 @@ void main() {
VkPhysicalDeviceFeatures deviceFeatures{}; VkPhysicalDeviceFeatures deviceFeatures{};
deviceFeatures.geometryShader = supportedDeviceFeatures.geometryShader; deviceFeatures.geometryShader = supportedDeviceFeatures.geometryShader;
deviceFeatures.independentBlend = supportedDeviceFeatures.independentBlend; deviceFeatures.independentBlend = supportedDeviceFeatures.independentBlend;
deviceFeatures.logicOp = supportedDeviceFeatures.logicOp;
deviceFeatures.shaderClipDistance = supportedDeviceFeatures.shaderClipDistance; deviceFeatures.shaderClipDistance = supportedDeviceFeatures.shaderClipDistance;
deviceFeatures.shaderCullDistance = supportedDeviceFeatures.shaderCullDistance; deviceFeatures.shaderCullDistance = supportedDeviceFeatures.shaderCullDistance;
deviceFeatures.wideLines = supportedDeviceFeatures.wideLines;
m_logicOpFeatureEnabled = deviceFeatures.logicOp == VK_TRUE;
deviceFeatures.shaderInt64 = supportedDeviceFeatures.shaderInt64; deviceFeatures.shaderInt64 = supportedDeviceFeatures.shaderInt64;
deviceFeatures.drawIndirectFirstInstance = supportedDeviceFeatures.drawIndirectFirstInstance; deviceFeatures.drawIndirectFirstInstance = supportedDeviceFeatures.drawIndirectFirstInstance;
m_logicOpFeatureEnabled = deviceFeatures.logicOp == VK_TRUE;
VkDeviceCreateInfo deviceCreateInfo{}; VkDeviceCreateInfo deviceCreateInfo{};
deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
@@ -5042,18 +5254,24 @@ void main() {
deviceCreateInfo.enabledExtensionCount = static_cast<Uint32>(enabledDeviceExtensions.size()); deviceCreateInfo.enabledExtensionCount = static_cast<Uint32>(enabledDeviceExtensions.size());
deviceCreateInfo.ppEnabledExtensionNames = enabledDeviceExtensions.data(); deviceCreateInfo.ppEnabledExtensionNames = enabledDeviceExtensions.data();
MGLOG_I("Device feature support: geometryShader=%s independentBlend=%s shaderClipDistance=%s shaderCullDistance=%s shaderInt64=%s drawIndirectFirstInstance=%s", MGLOG_I("Device feature support: geometryShader=%s independentBlend=%s logicOp=%s shaderClipDistance=%s "
"shaderCullDistance=%s wideLines=%s shaderInt64=%s drawIndirectFirstInstance=%s",
supportedDeviceFeatures.geometryShader ? "true" : "false", supportedDeviceFeatures.geometryShader ? "true" : "false",
supportedDeviceFeatures.independentBlend ? "true" : "false", supportedDeviceFeatures.independentBlend ? "true" : "false",
supportedDeviceFeatures.logicOp ? "true" : "false",
supportedDeviceFeatures.shaderClipDistance ? "true" : "false", supportedDeviceFeatures.shaderClipDistance ? "true" : "false",
supportedDeviceFeatures.shaderCullDistance ? "true" : "false", supportedDeviceFeatures.shaderCullDistance ? "true" : "false",
supportedDeviceFeatures.wideLines ? "true" : "false",
supportedDeviceFeatures.shaderInt64 ? "true" : "false", supportedDeviceFeatures.shaderInt64 ? "true" : "false",
supportedDeviceFeatures.drawIndirectFirstInstance ? "true" : "false"); supportedDeviceFeatures.drawIndirectFirstInstance ? "true" : "false");
MGLOG_I("Device feature enabled: geometryShader=%s independentBlend=%s shaderClipDistance=%s shaderCullDistance=%s shaderInt64=%s drawIndirectFirstInstance=%s", MGLOG_I("Device feature enabled: geometryShader=%s independentBlend=%s logicOp=%s shaderClipDistance=%s "
"shaderCullDistance=%s wideLines=%s shaderInt64=%s drawIndirectFirstInstance=%s",
deviceFeatures.geometryShader ? "true" : "false", deviceFeatures.geometryShader ? "true" : "false",
deviceFeatures.independentBlend ? "true" : "false", deviceFeatures.independentBlend ? "true" : "false",
deviceFeatures.logicOp ? "true" : "false",
deviceFeatures.shaderClipDistance ? "true" : "false", deviceFeatures.shaderClipDistance ? "true" : "false",
deviceFeatures.shaderCullDistance ? "true" : "false", deviceFeatures.shaderCullDistance ? "true" : "false",
deviceFeatures.wideLines ? "true" : "false",
deviceFeatures.shaderInt64 ? "true" : "false", deviceFeatures.shaderInt64 ? "true" : "false",
deviceFeatures.drawIndirectFirstInstance ? "true" : "false"); deviceFeatures.drawIndirectFirstInstance ? "true" : "false");
VK_VERIFY(vkCreateDevice(m_physicalDevice.handle, &deviceCreateInfo, nullptr, &m_device), "vkCreateDevice"); VK_VERIFY(vkCreateDevice(m_physicalDevice.handle, &deviceCreateInfo, nullptr, &m_device), "vkCreateDevice");
@@ -5362,12 +5580,13 @@ void main() {
clearRect.layerCount = 1; clearRect.layerCount = 1;
for (const auto& pending : compatibleRenderPassEntry.pendingClearAttachments) { for (const auto& pending : compatibleRenderPassEntry.pendingClearAttachments) {
if (!pending.texture) { if (pending.key.texture == nullptr) {
continue; continue;
} }
ClearAttachmentPayload clearPayload{}; ClearAttachmentPayload clearPayload{};
if (!m_clearManager->GetPendingClear(pending.texture, clearPayload)) { SharedPtr<MG_State::GLState::ITextureObject> liveTexture;
if (!m_clearManager->GetPendingClear(pending.key, clearPayload, liveTexture)) {
continue; continue;
} }
@@ -5380,7 +5599,7 @@ void main() {
clearPayload.color.x(), clearPayload.color.x(),
clearPayload.color.y(), clearPayload.color.y(),
clearPayload.color.z(), clearPayload.color.z(),
ResolveColorClearAlpha(pending.texture, clearPayload.color.w()) ResolveColorClearAlpha(liveTexture.get(), clearPayload.color.w())
}; };
} else { } else {
if ((clearPayload.mask & GL_DEPTH_BUFFER_BIT) != 0) { if ((clearPayload.mask & GL_DEPTH_BUFFER_BIT) != 0) {
@@ -5397,7 +5616,7 @@ void main() {
} }
vkCmdClearAttachments(commandBuffer, 1, &clearAttachment, 1, &clearRect); vkCmdClearAttachments(commandBuffer, 1, &clearAttachment, 1, &clearRect);
m_clearManager->PopPendingClear(pending.texture); m_clearManager->PopPendingClear(pending.key);
} }
} }
@@ -217,6 +217,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
VkQueue m_presentQueue = VK_NULL_HANDLE; VkQueue m_presentQueue = VK_NULL_HANDLE;
Bool m_drawIndirectCountExtensionEnabled = false; Bool m_drawIndirectCountExtensionEnabled = false;
Bool m_indexTypeUint8ExtensionEnabled = false; Bool m_indexTypeUint8ExtensionEnabled = false;
Bool m_logicOpFeatureEnabled = false;
using PFNDrawIndexedIndirectCountFunc = void(VKAPI_PTR*)(VkCommandBuffer commandBuffer, VkBuffer buffer, using PFNDrawIndexedIndirectCountFunc = void(VKAPI_PTR*)(VkCommandBuffer commandBuffer, VkBuffer buffer,
VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize offset, VkBuffer countBuffer,
VkDeviceSize countBufferOffset, Uint32 maxDrawCount, VkDeviceSize countBufferOffset, Uint32 maxDrawCount,
+3
View File
@@ -258,6 +258,9 @@ namespace MobileGL::MG_Impl::EGLImpl {
if (!state) { if (!state) {
return EGL_FALSE; return EGL_FALSE;
} }
if (auto* backendObject = MG_Backend::pActiveBackendObject.get()) {
(void)backendObject->MakeEGLCurrent(EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
}
state->ReleaseThread(); state->ReleaseThread();
return EGL_TRUE; return EGL_TRUE;
} }
+15 -7
View File
@@ -1268,6 +1268,7 @@ namespace MobileGL::MG_Impl::GLImpl {
if (!BufferImpl::ValidateBufferBindingPointTarget(bufferTarget)) return; if (!BufferImpl::ValidateBufferBindingPointTarget(bufferTarget)) return;
auto& point = MG_State::pGLContext->GetBufferBindingPoint(bufferTarget, pointIndex); auto& point = MG_State::pGLContext->GetBufferBindingPoint(bufferTarget, pointIndex);
SharedPtr<MG_State::GLState::BufferObject> bufferObject;
if (buffer == 0) { if (buffer == 0) {
point.Bind(nullptr); point.Bind(nullptr);
point.SetRange(Range1D(0, 0)); point.SetRange(Range1D(0, 0));
@@ -1278,11 +1279,15 @@ namespace MobileGL::MG_Impl::GLImpl {
if (!doesBufferObjectCreated) { if (!doesBufferObjectCreated) {
MG_State::pGLContext->CreateBufferObject(buffer); MG_State::pGLContext->CreateBufferObject(buffer);
} }
auto& bufferObject = MG_State::pGLContext->GetBufferObject(buffer); bufferObject = MG_State::pGLContext->GetBufferObject(buffer);
point.Bind(bufferObject); point.Bind(bufferObject);
if (bufferObject) {
point.SetRange(Range1D(0, bufferObject->GetSize())); point.SetRange(Range1D(0, bufferObject->GetSize()));
MGLOG_D("%s: set range (0, %d)", __func__, bufferObject->GetSize()); MGLOG_D("%s: set range (0, %d)", __func__, bufferObject->GetSize());
} else {
point.ClearRange();
}
} }
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) {
@@ -1292,6 +1297,7 @@ namespace MobileGL::MG_Impl::GLImpl {
if (!BufferImpl::ValidateBufferBindingPointTarget(bufferTarget)) return; if (!BufferImpl::ValidateBufferBindingPointTarget(bufferTarget)) return;
auto& point = MG_State::pGLContext->GetBufferBindingPoint(bufferTarget, index); auto& point = MG_State::pGLContext->GetBufferBindingPoint(bufferTarget, index);
SharedPtr<MG_State::GLState::BufferObject> bufferObject;
if (buffer == 0) { if (buffer == 0) {
point.Bind(nullptr); point.Bind(nullptr);
point.SetRange(Range1D(0, 0)); point.SetRange(Range1D(0, 0));
@@ -1302,10 +1308,14 @@ namespace MobileGL::MG_Impl::GLImpl {
if (!doesBufferObjectCreated) { if (!doesBufferObjectCreated) {
MG_State::pGLContext->CreateBufferObject(buffer); MG_State::pGLContext->CreateBufferObject(buffer);
} }
auto& bufferObject = MG_State::pGLContext->GetBufferObject(buffer); bufferObject = MG_State::pGLContext->GetBufferObject(buffer);
point.Bind(bufferObject); point.Bind(bufferObject);
if (bufferObject) {
point.SetRange(Range1D(offset, offset + size)); point.SetRange(Range1D(offset, offset + size));
} else {
point.ClearRange();
}
} }
/* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */ /* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */
@@ -1313,14 +1323,12 @@ namespace MobileGL::MG_Impl::GLImpl {
GetBufferParameteriv_State(target, pname, params); GetBufferParameteriv_State(target, pname, params);
} }
void GetBufferParameteri64v(GLenum target, GLenum pname, GLint64* params) {
GetBufferParameteri64v_State(target, pname, params);
}
void GetBufferPointerv(GLenum target, GLenum pname, void** params) { void GetBufferPointerv(GLenum target, GLenum pname, void** params) {
GetBufferPointerv_State(target, pname, params); GetBufferPointerv_State(target, pname, params);
} }
void GetBufferParameteri64v(GLenum target, GLenum pname, GLint64* params) {
GetBufferParameteri64v_State(target, pname, params);
}
GLboolean IsBuffer(GLuint buffer) { GLboolean IsBuffer(GLuint buffer) {
return IsBuffer_State(buffer); return IsBuffer_State(buffer);
} }
@@ -12,6 +12,62 @@
#include <MG_Backend/BackendObjects.h> #include <MG_Backend/BackendObjects.h>
namespace MobileGL::MG_Impl::GLImpl { namespace MobileGL::MG_Impl::GLImpl {
static Bool ValidateCurrentProgramForExecution(const char* functionName) {
const auto& currentProgram = MG_State::pGLContext->GetCurrentProgram();
if (!currentProgram) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", functionName, "There is no current program object."));
return false;
}
if (!currentProgram->GetLinkStatus()) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", functionName,
"The current program object is not linked."));
return false;
}
return true;
}
static Bool ValidateCurrentProgramForCompute(const char* functionName) {
if (!ValidateCurrentProgramForExecution(functionName)) return false;
const auto& currentProgram = MG_State::pGLContext->GetCurrentProgram();
if (currentProgram->GetShaderIndexByStage(ShaderStage::Compute) < 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", functionName,
"The current program object has no compute shader stage."));
return false;
}
return true;
}
static Bool ValidatePrimitiveModeForBackend(const char* functionName, GLenum mode) {
const auto& activeBackendObject = MG_Backend::pActiveBackendObject;
if (!activeBackendObject) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", functionName, "No active backend object."));
return false;
}
if (activeBackendObject->GetBackendType() == BackendType::DirectVulkan && mode == GL_LINE_LOOP) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>(
"MG_Impl/GLImpl", functionName,
"Primitive mode GL_LINE_LOOP is not supported by the DirectVulkan backend."));
return false;
}
return true;
}
void Clear_Backend(GLbitfield mask) { void Clear_Backend(GLbitfield mask) {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
@@ -182,6 +238,7 @@ namespace MobileGL::MG_Impl::GLImpl {
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "Backend does not support compute dispatch.")); MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "Backend does not support compute dispatch."));
return; return;
} }
if (!ValidateCurrentProgramForCompute(__func__)) return;
dispatchCompute(numGroupsX, numGroupsY, numGroupsZ); dispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
} }
@@ -194,6 +251,7 @@ namespace MobileGL::MG_Impl::GLImpl {
"Backend does not support indirect compute dispatch.")); "Backend does not support indirect compute dispatch."));
return; return;
} }
if (!ValidateCurrentProgramForCompute(__func__)) return;
dispatchComputeIndirect(indirect); dispatchComputeIndirect(indirect);
} }
@@ -221,10 +279,14 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
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) {
if (!ValidateCurrentProgramForExecution(__func__)) return;
if (!ValidatePrimitiveModeForBackend(__func__, mode)) return;
MultiDrawElementsIndirect_Backend(mode, type, indirect, drawcount, stride); MultiDrawElementsIndirect_Backend(mode, type, indirect, drawcount, stride);
} }
void MultiDrawArraysIndirect(GLenum mode, const void* indirect, GLsizei drawcount, GLsizei stride) { void MultiDrawArraysIndirect(GLenum mode, const void* indirect, GLsizei drawcount, GLsizei stride) {
if (!ValidateCurrentProgramForExecution(__func__)) return;
if (!ValidatePrimitiveModeForBackend(__func__, mode)) return;
MultiDrawArraysIndirect_Backend(mode, indirect, drawcount, stride); MultiDrawArraysIndirect_Backend(mode, indirect, drawcount, stride);
} }
@@ -256,65 +318,93 @@ namespace MobileGL::MG_Impl::GLImpl {
void DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, void DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type,
const void* indices, GLint basevertex) { const void* indices, GLint basevertex) {
if (!ValidateCurrentProgramForExecution(__func__)) return;
if (!ValidatePrimitiveModeForBackend(__func__, mode)) return;
DrawRangeElementsBaseVertex_Backend(mode, start, end, count, type, indices, basevertex); DrawRangeElementsBaseVertex_Backend(mode, start, end, count, type, indices, 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) {
if (!ValidateCurrentProgramForExecution(__func__)) return;
if (!ValidatePrimitiveModeForBackend(__func__, mode)) return;
DrawRangeElements_Backend(mode, start, end, count, type, indices); DrawRangeElements_Backend(mode, start, end, count, type, indices);
} }
void DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices, void DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices,
GLsizei instancecount, GLint basevertex, GLuint baseinstance) { GLsizei instancecount, GLint basevertex, GLuint baseinstance) {
if (!ValidateCurrentProgramForExecution(__func__)) return;
if (!ValidatePrimitiveModeForBackend(__func__, mode)) return;
DrawElementsInstancedBaseVertexBaseInstance_Backend(mode, count, type, indices, instancecount, basevertex, DrawElementsInstancedBaseVertexBaseInstance_Backend(mode, count, type, indices, instancecount, basevertex,
baseinstance); baseinstance);
} }
void DrawElementsInstancedBaseVertex(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) {
if (!ValidateCurrentProgramForExecution(__func__)) return;
if (!ValidatePrimitiveModeForBackend(__func__, mode)) return;
DrawElementsInstancedBaseVertex_Backend(mode, count, type, indices, instancecount, basevertex); DrawElementsInstancedBaseVertex_Backend(mode, count, type, indices, instancecount, basevertex);
} }
void DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices, void DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices,
GLsizei instancecount, GLuint baseinstance) { GLsizei instancecount, GLuint baseinstance) {
if (!ValidateCurrentProgramForExecution(__func__)) return;
if (!ValidatePrimitiveModeForBackend(__func__, mode)) return;
DrawElementsInstancedBaseInstance_Backend(mode, count, type, indices, instancecount, baseinstance); DrawElementsInstancedBaseInstance_Backend(mode, count, type, indices, instancecount, 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) {
if (!ValidateCurrentProgramForExecution(__func__)) return;
if (!ValidatePrimitiveModeForBackend(__func__, mode)) return;
DrawElementsInstanced_Backend(mode, count, type, indices, instancecount); DrawElementsInstanced_Backend(mode, count, type, indices, instancecount);
} }
void DrawElementsIndirect(GLenum mode, GLenum type, const void* indirect) { void DrawElementsIndirect(GLenum mode, GLenum type, const void* indirect) {
if (!ValidateCurrentProgramForExecution(__func__)) return;
if (!ValidatePrimitiveModeForBackend(__func__, mode)) return;
DrawElementsIndirect_Backend(mode, type, indirect); DrawElementsIndirect_Backend(mode, type, indirect);
} }
void DrawArraysInstancedBaseInstance(GLenum mode, GLint first, GLsizei count, GLsizei instancecount, void DrawArraysInstancedBaseInstance(GLenum mode, GLint first, GLsizei count, GLsizei instancecount,
GLuint baseinstance) { GLuint baseinstance) {
if (!ValidateCurrentProgramForExecution(__func__)) return;
if (!ValidatePrimitiveModeForBackend(__func__, mode)) return;
DrawArraysInstancedBaseInstance_Backend(mode, first, count, instancecount, baseinstance); DrawArraysInstancedBaseInstance_Backend(mode, first, count, instancecount, baseinstance);
} }
void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount) { void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount) {
if (!ValidateCurrentProgramForExecution(__func__)) return;
if (!ValidatePrimitiveModeForBackend(__func__, mode)) return;
DrawArraysInstanced_Backend(mode, first, count, instancecount); DrawArraysInstanced_Backend(mode, first, count, instancecount);
} }
void DrawArraysIndirect(GLenum mode, const void* indirect) { void DrawArraysIndirect(GLenum mode, const void* indirect) {
if (!ValidateCurrentProgramForExecution(__func__)) return;
if (!ValidatePrimitiveModeForBackend(__func__, mode)) return;
DrawArraysIndirect_Backend(mode, indirect); DrawArraysIndirect_Backend(mode, 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) {
if (!ValidateCurrentProgramForExecution(__func__)) return;
if (!ValidatePrimitiveModeForBackend(__func__, mode)) return;
DrawElementsBaseVertex_Backend(mode, count, type, indices, basevertex); DrawElementsBaseVertex_Backend(mode, count, type, indices, basevertex);
} }
void DrawArrays(GLenum mode, GLint first, GLsizei count) { void DrawArrays(GLenum mode, GLint first, GLsizei count) {
if (!ValidateCurrentProgramForExecution(__func__)) return;
if (!ValidatePrimitiveModeForBackend(__func__, mode)) return;
DrawArrays_Backend(mode, first, count); DrawArrays_Backend(mode, first, count);
} }
void MultiDrawElements(GLenum mode, const GLsizei* count, GLenum type, const void* const* indices, void MultiDrawElements(GLenum mode, const GLsizei* count, GLenum type, const void* const* indices,
GLsizei drawcount) { GLsizei drawcount) {
if (!ValidateCurrentProgramForExecution(__func__)) return;
if (!ValidatePrimitiveModeForBackend(__func__, mode)) return;
MultiDrawElements_Backend(mode, count, type, indices, drawcount); MultiDrawElements_Backend(mode, count, type, indices, drawcount);
} }
void MultiDrawElementsBaseVertex(GLenum mode, const GLsizei* count, GLenum type, const void* const* indices, void MultiDrawElementsBaseVertex(GLenum mode, const GLsizei* count, GLenum type, const void* const* indices,
GLsizei drawcount, const GLint* basevertex) { GLsizei drawcount, const GLint* basevertex) {
if (!ValidateCurrentProgramForExecution(__func__)) return;
if (!ValidatePrimitiveModeForBackend(__func__, mode)) return;
MultiDrawElementsBaseVertex_Backend(mode, count, type, indices, drawcount, basevertex); MultiDrawElementsBaseVertex_Backend(mode, count, type, indices, drawcount, basevertex);
} }
@@ -323,6 +413,8 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
void DrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices) { void DrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices) {
if (!ValidateCurrentProgramForExecution(__func__)) return;
if (!ValidatePrimitiveModeForBackend(__func__, mode)) return;
DrawElements_Backend(mode, count, type, indices); DrawElements_Backend(mode, count, type, indices);
} }
@@ -17,6 +17,7 @@
#include "../RenderState/GL_RenderState.h" #include "../RenderState/GL_RenderState.h"
#include "../Framebuffer/GL_Framebuffer.h" #include "../Framebuffer/GL_Framebuffer.h"
#include "../VertexArray/GL_VertexArray.h" #include "../VertexArray/GL_VertexArray.h"
#include "../Sync/GL_Sync.h"
#define DECLARE_GL_FUNCTION_STUB_HEAD(type, name, ...) MOBILEGL_GL_API type gl##name(__VA_ARGS__) { #define DECLARE_GL_FUNCTION_STUB_HEAD(type, name, ...) MOBILEGL_GL_API type gl##name(__VA_ARGS__) {
@@ -76,7 +77,7 @@ DECLARE_GL_FUNCTION_HEAD(void, BufferSubData, GLenum target, GLintptr offset, GL
DECLARE_GL_FUNCTION_HEAD(GLenum, CheckFramebufferStatus, GLenum target) DECLARE_GL_FUNCTION_END(GLenum, CheckFramebufferStatus, target) DECLARE_GL_FUNCTION_HEAD(GLenum, CheckFramebufferStatus, GLenum target) DECLARE_GL_FUNCTION_END(GLenum, CheckFramebufferStatus, target)
DECLARE_GL_FUNCTION_HEAD(void, Clear, GLbitfield mask) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Clear, mask) DECLARE_GL_FUNCTION_HEAD(void, Clear, GLbitfield mask) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Clear, mask)
DECLARE_GL_FUNCTION_HEAD(void, ClearColor, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ClearColor, red, green, blue, alpha) DECLARE_GL_FUNCTION_HEAD(void, ClearColor, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ClearColor, red, green, blue, alpha)
DECLARE_GL_FUNCTION_STUB_HEAD(void, ClearDepthf, GLfloat d) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClearDepthf, d) DECLARE_GL_FUNCTION_HEAD(void, ClearDepthf, GLfloat d) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ClearDepth, static_cast<GLclampd>(d))
DECLARE_GL_FUNCTION_HEAD(void, ClearStencil, GLint s) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ClearStencil, s) DECLARE_GL_FUNCTION_HEAD(void, ClearStencil, GLint s) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ClearStencil, s)
DECLARE_GL_FUNCTION_HEAD(void, ColorMask, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ColorMask, red, green, blue, alpha) DECLARE_GL_FUNCTION_HEAD(void, ColorMask, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ColorMask, red, green, blue, alpha)
DECLARE_GL_FUNCTION_HEAD(void, CompileShader, GLuint shader) DECLARE_GL_FUNCTION_END_NO_RETURN(void, CompileShader, shader) DECLARE_GL_FUNCTION_HEAD(void, CompileShader, GLuint shader) DECLARE_GL_FUNCTION_END_NO_RETURN(void, CompileShader, shader)
@@ -95,7 +96,7 @@ DECLARE_GL_FUNCTION_HEAD(void, DeleteShader, GLuint shader) DECLARE_GL_FUNCTION_
DECLARE_GL_FUNCTION_HEAD(void, DeleteTextures, GLsizei n, const GLuint* textures) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DeleteTextures, n, textures) DECLARE_GL_FUNCTION_HEAD(void, DeleteTextures, GLsizei n, const GLuint* textures) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DeleteTextures, n, textures)
DECLARE_GL_FUNCTION_HEAD(void, DepthFunc, GLenum func) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DepthFunc, func) DECLARE_GL_FUNCTION_HEAD(void, DepthFunc, GLenum func) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DepthFunc, func)
DECLARE_GL_FUNCTION_HEAD(void, DepthMask, GLboolean flag) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DepthMask, flag) DECLARE_GL_FUNCTION_HEAD(void, DepthMask, GLboolean flag) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DepthMask, flag)
DECLARE_GL_FUNCTION_STUB_HEAD(void, DepthRangef, GLfloat n, GLfloat f) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DepthRangef, n, f) DECLARE_GL_FUNCTION_HEAD(void, DepthRangef, GLfloat n, GLfloat f) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DepthRange, static_cast<GLclampd>(n), static_cast<GLclampd>(f))
DECLARE_GL_FUNCTION_HEAD(void, DetachShader, GLuint program, GLuint shader) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DetachShader, program, shader) DECLARE_GL_FUNCTION_HEAD(void, DetachShader, GLuint program, GLuint shader) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DetachShader, program, shader)
DECLARE_GL_FUNCTION_HEAD(void, Disable, GLenum cap) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Disable, cap) DECLARE_GL_FUNCTION_HEAD(void, Disable, GLenum cap) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Disable, cap)
DECLARE_GL_FUNCTION_HEAD(void, DisableVertexAttribArray, GLuint index) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DisableVertexAttribArray, index) DECLARE_GL_FUNCTION_HEAD(void, DisableVertexAttribArray, GLuint index) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DisableVertexAttribArray, index)
@@ -117,10 +118,10 @@ DECLARE_GL_FUNCTION_HEAD(void, GetActiveAttrib, GLuint program, GLuint index, GL
DECLARE_GL_FUNCTION_HEAD(void, GetActiveUniform, GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetActiveUniform, program, index, bufSize, length, size, type, name) DECLARE_GL_FUNCTION_HEAD(void, GetActiveUniform, GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetActiveUniform, program, index, bufSize, length, size, type, name)
DECLARE_GL_FUNCTION_HEAD(void, GetAttachedShaders, GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetAttachedShaders, program, maxCount, count, shaders) DECLARE_GL_FUNCTION_HEAD(void, GetAttachedShaders, GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetAttachedShaders, program, maxCount, count, shaders)
DECLARE_GL_FUNCTION_HEAD(GLint, GetAttribLocation, GLuint program, const GLchar* name) DECLARE_GL_FUNCTION_END(GLint, GetAttribLocation, program, name) DECLARE_GL_FUNCTION_HEAD(GLint, GetAttribLocation, GLuint program, const GLchar* name) DECLARE_GL_FUNCTION_END(GLint, GetAttribLocation, program, name)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetBooleanv, GLenum pname, GLboolean* data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetBooleanv, pname, data) DECLARE_GL_FUNCTION_HEAD(void, GetBooleanv, GLenum pname, GLboolean* data) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetBooleanv, pname, data)
DECLARE_GL_FUNCTION_HEAD(void, GetBufferParameteriv, GLenum target, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetBufferParameteriv, target, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetBufferParameteriv, GLenum target, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetBufferParameteriv, target, pname, params)
DECLARE_GL_FUNCTION_HEAD(GLenum, GetError) DECLARE_GL_FUNCTION_END(GLenum, GetError) DECLARE_GL_FUNCTION_HEAD(GLenum, GetError) DECLARE_GL_FUNCTION_END(GLenum, GetError)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetFloatv, GLenum pname, GLfloat* data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetFloatv, pname, data) DECLARE_GL_FUNCTION_HEAD(void, GetFloatv, GLenum pname, GLfloat* data) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetFloatv, pname, data)
DECLARE_GL_FUNCTION_HEAD(void, GetFramebufferAttachmentParameteriv, GLenum target, GLenum attachment, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetFramebufferAttachmentParameteriv, target, attachment, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetFramebufferAttachmentParameteriv, GLenum target, GLenum attachment, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetFramebufferAttachmentParameteriv, target, attachment, pname, params)
DECLARE_GL_FUNCTION_HEAD(void, GetIntegerv, GLenum pname, GLint* data) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetIntegerv, pname, data) DECLARE_GL_FUNCTION_HEAD(void, GetIntegerv, GLenum pname, GLint* data) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetIntegerv, pname, data)
DECLARE_GL_FUNCTION_HEAD(void, GetProgramiv, GLuint program, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetProgramiv, program, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetProgramiv, GLuint program, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetProgramiv, program, pname, params)
@@ -135,9 +136,9 @@ DECLARE_GL_FUNCTION_HEAD(void, GetTexParameteriv, GLenum target, GLenum pname, G
DECLARE_GL_FUNCTION_HEAD(void, GetUniformfv, GLuint program, GLint location, GLfloat* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetUniformfv, program, location, params) DECLARE_GL_FUNCTION_HEAD(void, GetUniformfv, GLuint program, GLint location, GLfloat* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetUniformfv, program, location, params)
DECLARE_GL_FUNCTION_HEAD(void, GetUniformiv, GLuint program, GLint location, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetUniformiv, program, location, params) DECLARE_GL_FUNCTION_HEAD(void, GetUniformiv, GLuint program, GLint location, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetUniformiv, program, location, params)
DECLARE_GL_FUNCTION_HEAD(GLint, GetUniformLocation, GLuint program, const GLchar* name) DECLARE_GL_FUNCTION_END(GLint, GetUniformLocation, program, name) DECLARE_GL_FUNCTION_HEAD(GLint, GetUniformLocation, GLuint program, const GLchar* name) DECLARE_GL_FUNCTION_END(GLint, GetUniformLocation, program, name)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetVertexAttribfv, GLuint index, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetVertexAttribfv, index, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetVertexAttribfv, GLuint index, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetVertexAttribfv, index, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetVertexAttribiv, GLuint index, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetVertexAttribiv, index, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetVertexAttribiv, GLuint index, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetVertexAttribiv, index, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetVertexAttribPointerv, GLuint index, GLenum pname, void** pointer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetVertexAttribPointerv, index, pname, pointer) DECLARE_GL_FUNCTION_HEAD(void, GetVertexAttribPointerv, GLuint index, GLenum pname, void** pointer) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetVertexAttribPointerv, index, pname, pointer)
DECLARE_GL_FUNCTION_HEAD(void, Hint, GLenum target, GLenum mode) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Hint, target, mode) DECLARE_GL_FUNCTION_HEAD(void, Hint, GLenum target, GLenum mode) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Hint, target, mode)
DECLARE_GL_FUNCTION_HEAD(GLboolean, IsBuffer, GLuint buffer) DECLARE_GL_FUNCTION_END(GLboolean, IsBuffer, buffer) DECLARE_GL_FUNCTION_HEAD(GLboolean, IsBuffer, GLuint buffer) DECLARE_GL_FUNCTION_END(GLboolean, IsBuffer, buffer)
DECLARE_GL_FUNCTION_HEAD(GLboolean, IsEnabled, GLenum cap) DECLARE_GL_FUNCTION_END(GLboolean, IsEnabled, cap) DECLARE_GL_FUNCTION_HEAD(GLboolean, IsEnabled, GLenum cap) DECLARE_GL_FUNCTION_END(GLboolean, IsEnabled, cap)
@@ -190,14 +191,14 @@ DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix3fv, GLint location, GLsizei count,
DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix4fv, location, count, transpose, value) DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix4fv, location, count, transpose, value)
DECLARE_GL_FUNCTION_HEAD(void, UseProgram, GLuint program) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UseProgram, program) DECLARE_GL_FUNCTION_HEAD(void, UseProgram, GLuint program) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UseProgram, program)
DECLARE_GL_FUNCTION_HEAD(void, ValidateProgram, GLuint program) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ValidateProgram, program) DECLARE_GL_FUNCTION_HEAD(void, ValidateProgram, GLuint program) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ValidateProgram, program)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib1f, GLuint index, GLfloat x) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib1f, index, x) DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib1f, GLuint index, GLfloat x) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib1f, index, x)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib1fv, GLuint index, const GLfloat* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib1fv, index, v) DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib1fv, GLuint index, const GLfloat* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib1fv, index, v)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib2f, GLuint index, GLfloat x, GLfloat y) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib2f, index, x, y) DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib2f, GLuint index, GLfloat x, GLfloat y) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib2f, index, x, y)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib2fv, GLuint index, const GLfloat* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib2fv, index, v) DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib2fv, GLuint index, const GLfloat* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib2fv, index, v)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib3f, GLuint index, GLfloat x, GLfloat y, GLfloat z) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib3f, index, x, y, z) DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib3f, GLuint index, GLfloat x, GLfloat y, GLfloat z) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib3f, index, x, y, z)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib3fv, GLuint index, const GLfloat* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib3fv, index, v) DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib3fv, GLuint index, const GLfloat* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib3fv, index, v)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4f, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4f, index, x, y, z, w) DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib4f, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib4f, index, x, y, z, w)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4fv, GLuint index, const GLfloat* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4fv, index, v) DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib4fv, GLuint index, const GLfloat* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib4fv, index, v)
DECLARE_GL_FUNCTION_HEAD(void, VertexAttribPointer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribPointer, index, size, type, normalized, stride, pointer) DECLARE_GL_FUNCTION_HEAD(void, VertexAttribPointer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribPointer, index, size, type, normalized, stride, pointer)
DECLARE_GL_FUNCTION_HEAD(void, Viewport, GLint x, GLint y, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Viewport, x, y, width, height) DECLARE_GL_FUNCTION_HEAD(void, Viewport, GLint x, GLint y, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Viewport, x, y, width, height)
DECLARE_GL_FUNCTION_HEAD(void, ReadBuffer, GLenum src) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ReadBuffer, src) DECLARE_GL_FUNCTION_HEAD(void, ReadBuffer, GLenum src) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ReadBuffer, src)
@@ -240,28 +241,28 @@ DECLARE_GL_FUNCTION_HEAD(void, BindBufferBase, GLenum target, GLuint index, GLui
DECLARE_GL_FUNCTION_STUB_HEAD(void, TransformFeedbackVaryings, GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TransformFeedbackVaryings, program, count, varyings, bufferMode) DECLARE_GL_FUNCTION_STUB_HEAD(void, TransformFeedbackVaryings, GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TransformFeedbackVaryings, program, count, varyings, bufferMode)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetTransformFeedbackVarying, GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTransformFeedbackVarying, program, index, bufSize, length, size, type, name) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetTransformFeedbackVarying, GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTransformFeedbackVarying, program, index, bufSize, length, size, type, name)
DECLARE_GL_FUNCTION_HEAD(void, VertexAttribIPointer, GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribIPointer, index, size, type, stride, pointer) DECLARE_GL_FUNCTION_HEAD(void, VertexAttribIPointer, GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribIPointer, index, size, type, stride, pointer)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetVertexAttribIiv, GLuint index, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetVertexAttribIiv, index, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetVertexAttribIiv, GLuint index, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetVertexAttribIiv, index, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetVertexAttribIuiv, GLuint index, GLenum pname, GLuint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetVertexAttribIuiv, index, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetVertexAttribIuiv, GLuint index, GLenum pname, GLuint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetVertexAttribIuiv, index, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribI4i, GLuint index, GLint x, GLint y, GLint z, GLint w) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribI4i, index, x, y, z, w) DECLARE_GL_FUNCTION_HEAD(void, VertexAttribI4i, GLuint index, GLint x, GLint y, GLint z, GLint w) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribI4i, index, x, y, z, w)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribI4ui, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribI4ui, index, x, y, z, w) DECLARE_GL_FUNCTION_HEAD(void, VertexAttribI4ui, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribI4ui, index, x, y, z, w)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribI4iv, GLuint index, const GLint* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribI4iv, index, v) DECLARE_GL_FUNCTION_HEAD(void, VertexAttribI4iv, GLuint index, const GLint* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribI4iv, index, v)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribI4uiv, GLuint index, const GLuint* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribI4uiv, index, v) DECLARE_GL_FUNCTION_HEAD(void, VertexAttribI4uiv, GLuint index, const GLuint* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribI4uiv, index, v)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetUniformuiv, GLuint program, GLint location, GLuint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetUniformuiv, program, location, params) DECLARE_GL_FUNCTION_HEAD(void, GetUniformuiv, GLuint program, GLint location, GLuint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetUniformuiv, program, location, params)
DECLARE_GL_FUNCTION_HEAD(GLint, GetFragDataLocation, GLuint program, const GLchar* name) DECLARE_GL_FUNCTION_END(GLint, GetFragDataLocation, program, name) DECLARE_GL_FUNCTION_HEAD(GLint, GetFragDataLocation, GLuint program, const GLchar* name) DECLARE_GL_FUNCTION_END(GLint, GetFragDataLocation, program, name)
DECLARE_GL_FUNCTION_HEAD(void, Uniform1ui, GLint location, GLuint v0) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform1ui, location, v0) DECLARE_GL_FUNCTION_HEAD(void, Uniform1ui, GLint location, GLuint v0) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform1ui, location, v0)
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform2ui, GLint location, GLuint v0, GLuint v1) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform2ui, location, v0, v1) DECLARE_GL_FUNCTION_HEAD(void, Uniform2ui, GLint location, GLuint v0, GLuint v1) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform2ui, location, v0, v1)
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform3ui, GLint location, GLuint v0, GLuint v1, GLuint v2) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform3ui, location, v0, v1, v2) DECLARE_GL_FUNCTION_HEAD(void, Uniform3ui, GLint location, GLuint v0, GLuint v1, GLuint v2) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform3ui, location, v0, v1, v2)
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform4ui, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform4ui, location, v0, v1, v2, v3) DECLARE_GL_FUNCTION_HEAD(void, Uniform4ui, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform4ui, location, v0, v1, v2, v3)
DECLARE_GL_FUNCTION_HEAD(void, Uniform1uiv, GLint location, GLsizei count, const GLuint* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform1uiv, location, count, value) DECLARE_GL_FUNCTION_HEAD(void, Uniform1uiv, GLint location, GLsizei count, const GLuint* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform1uiv, location, count, value)
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform2uiv, GLint location, GLsizei count, const GLuint* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform2uiv, location, count, value) DECLARE_GL_FUNCTION_HEAD(void, Uniform2uiv, GLint location, GLsizei count, const GLuint* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform2uiv, location, count, value)
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform3uiv, GLint location, GLsizei count, const GLuint* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform3uiv, location, count, value) DECLARE_GL_FUNCTION_HEAD(void, Uniform3uiv, GLint location, GLsizei count, const GLuint* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform3uiv, location, count, value)
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform4uiv, GLint location, GLsizei count, const GLuint* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform4uiv, location, count, value) DECLARE_GL_FUNCTION_HEAD(void, Uniform4uiv, GLint location, GLsizei count, const GLuint* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform4uiv, location, count, value)
DECLARE_GL_FUNCTION_HEAD(void, ClearBufferiv, GLenum buffer, GLint drawbuffer, const GLint* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ClearBufferiv, buffer, drawbuffer, value) DECLARE_GL_FUNCTION_HEAD(void, ClearBufferiv, GLenum buffer, GLint drawbuffer, const GLint* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ClearBufferiv, buffer, drawbuffer, value)
DECLARE_GL_FUNCTION_HEAD(void, ClearBufferuiv, GLenum buffer, GLint drawbuffer, const GLuint* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ClearBufferuiv, buffer, drawbuffer, value) DECLARE_GL_FUNCTION_HEAD(void, ClearBufferuiv, GLenum buffer, GLint drawbuffer, const GLuint* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ClearBufferuiv, buffer, drawbuffer, value)
DECLARE_GL_FUNCTION_HEAD(void, ClearBufferfv, GLenum buffer, GLint drawbuffer, const GLfloat* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ClearBufferfv, buffer, drawbuffer, value) DECLARE_GL_FUNCTION_HEAD(void, ClearBufferfv, GLenum buffer, GLint drawbuffer, const GLfloat* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ClearBufferfv, buffer, drawbuffer, value)
DECLARE_GL_FUNCTION_HEAD(void, ClearBufferfi, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ClearBufferfi, buffer, drawbuffer, depth, stencil) DECLARE_GL_FUNCTION_HEAD(void, ClearBufferfi, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ClearBufferfi, buffer, drawbuffer, depth, stencil)
DECLARE_GL_FUNCTION_HEAD(void, CopyBufferSubData, GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) DECLARE_GL_FUNCTION_END_NO_RETURN(void, CopyBufferSubData, readTarget, writeTarget, readOffset, writeOffset, size) DECLARE_GL_FUNCTION_HEAD(void, CopyBufferSubData, GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) DECLARE_GL_FUNCTION_END_NO_RETURN(void, CopyBufferSubData, readTarget, writeTarget, readOffset, writeOffset, size)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetUniformIndices, GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetUniformIndices, program, uniformCount, uniformNames, uniformIndices) DECLARE_GL_FUNCTION_HEAD(void, GetUniformIndices, GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetUniformIndices, program, uniformCount, uniformNames, uniformIndices)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetActiveUniformsiv, GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetActiveUniformsiv, program, uniformCount, uniformIndices, pname, params) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetActiveUniformsiv, GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetActiveUniformsiv, program, uniformCount, uniformIndices, pname, params)
DECLARE_GL_FUNCTION_HEAD(GLuint, GetUniformBlockIndex, GLuint program, const GLchar* uniformBlockName) DECLARE_GL_FUNCTION_END(GLuint, GetUniformBlockIndex, program, uniformBlockName) DECLARE_GL_FUNCTION_HEAD(GLuint, GetUniformBlockIndex, GLuint program, const GLchar* uniformBlockName) DECLARE_GL_FUNCTION_END(GLuint, GetUniformBlockIndex, program, uniformBlockName)
DECLARE_GL_FUNCTION_HEAD(void, GetActiveUniformBlockiv, GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetActiveUniformBlockiv, program, uniformBlockIndex, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetActiveUniformBlockiv, GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetActiveUniformBlockiv, program, uniformBlockIndex, pname, params)
@@ -300,9 +301,9 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramBinary, GLuint program, GLenum binary
DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramParameteri, GLuint program, GLenum pname, GLint value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramParameteri, program, pname, value) DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramParameteri, GLuint program, GLenum pname, GLint value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramParameteri, program, pname, value)
DECLARE_GL_FUNCTION_STUB_HEAD(void, InvalidateFramebuffer, GLenum target, GLsizei numAttachments, const GLenum* attachments) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, InvalidateFramebuffer, target, numAttachments, attachments) DECLARE_GL_FUNCTION_STUB_HEAD(void, InvalidateFramebuffer, GLenum target, GLsizei numAttachments, const GLenum* attachments) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, InvalidateFramebuffer, target, numAttachments, attachments)
DECLARE_GL_FUNCTION_STUB_HEAD(void, InvalidateSubFramebuffer, GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, InvalidateSubFramebuffer, target, numAttachments, attachments, x, y, width, height) DECLARE_GL_FUNCTION_STUB_HEAD(void, InvalidateSubFramebuffer, GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, InvalidateSubFramebuffer, target, numAttachments, attachments, x, y, width, height)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexStorage2D, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexStorage2D, target, levels, internalformat, width, height) DECLARE_GL_FUNCTION_HEAD(void, TexStorage2D, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexStorage2D, target, levels, internalformat, width, height)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexStorage3D, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexStorage3D, target, levels, internalformat, width, height, depth) DECLARE_GL_FUNCTION_HEAD(void, TexStorage3D, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexStorage3D, target, levels, internalformat, width, height, depth)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetInternalformativ, GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetInternalformativ, target, internalformat, pname, bufSize, params) DECLARE_GL_FUNCTION_HEAD(void, GetInternalformativ, GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetInternalformativ, target, internalformat, pname, bufSize, params)
DECLARE_GL_FUNCTION_HEAD(void, DispatchCompute, GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DispatchCompute, num_groups_x, num_groups_y, num_groups_z) DECLARE_GL_FUNCTION_HEAD(void, DispatchCompute, GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DispatchCompute, num_groups_x, num_groups_y, num_groups_z)
DECLARE_GL_FUNCTION_HEAD(void, DispatchComputeIndirect, GLintptr indirect) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DispatchComputeIndirect, indirect) DECLARE_GL_FUNCTION_HEAD(void, DispatchComputeIndirect, GLintptr indirect) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DispatchComputeIndirect, indirect)
DECLARE_GL_FUNCTION_HEAD(void, DrawArraysIndirect, GLenum mode, const void* indirect) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DrawArraysIndirect, mode, indirect) DECLARE_GL_FUNCTION_HEAD(void, DrawArraysIndirect, GLenum mode, const void* indirect) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DrawArraysIndirect, mode, indirect)
@@ -358,11 +359,11 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniformMatrix4x3fv, GLuint program, G
DECLARE_GL_FUNCTION_STUB_HEAD(void, ValidateProgramPipeline, GLuint pipeline) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ValidateProgramPipeline, pipeline) DECLARE_GL_FUNCTION_STUB_HEAD(void, ValidateProgramPipeline, GLuint pipeline) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ValidateProgramPipeline, pipeline)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetProgramPipelineInfoLog, GLuint pipeline, GLsizei bufSize, GLsizei* length, GLchar* infoLog) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetProgramPipelineInfoLog, pipeline, bufSize, length, infoLog) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetProgramPipelineInfoLog, GLuint pipeline, GLsizei bufSize, GLsizei* length, GLchar* infoLog) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetProgramPipelineInfoLog, pipeline, bufSize, length, infoLog)
DECLARE_GL_FUNCTION_HEAD(void, BindImageTexture, GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BindImageTexture, unit, texture, level, layered, layer, access, format) DECLARE_GL_FUNCTION_HEAD(void, BindImageTexture, GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BindImageTexture, unit, texture, level, layered, layer, access, format)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetBooleani_v, GLenum target, GLuint index, GLboolean* data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetBooleani_v, target, index, data) DECLARE_GL_FUNCTION_HEAD(void, GetBooleani_v, GLenum target, GLuint index, GLboolean* data) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetBooleani_v, target, index, data)
DECLARE_GL_FUNCTION_HEAD(void, MemoryBarrier, GLbitfield barriers) DECLARE_GL_FUNCTION_END_NO_RETURN(void, MemoryBarrier, barriers) DECLARE_GL_FUNCTION_HEAD(void, MemoryBarrier, GLbitfield barriers) DECLARE_GL_FUNCTION_END_NO_RETURN(void, MemoryBarrier, barriers)
DECLARE_GL_FUNCTION_HEAD(void, MemoryBarrierByRegion, GLbitfield barriers) DECLARE_GL_FUNCTION_END_NO_RETURN(void, MemoryBarrierByRegion, barriers) DECLARE_GL_FUNCTION_HEAD(void, MemoryBarrierByRegion, GLbitfield barriers) DECLARE_GL_FUNCTION_END_NO_RETURN(void, MemoryBarrierByRegion, barriers)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexStorage2DMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexStorage2DMultisample, target, samples, internalformat, width, height, fixedsamplelocations) DECLARE_GL_FUNCTION_HEAD(void, TexStorage2DMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexStorage2DMultisample, target, samples, internalformat, width, height, fixedsamplelocations)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetMultisamplefv, GLenum pname, GLuint index, GLfloat* val) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetMultisamplefv, pname, index, val) DECLARE_GL_FUNCTION_HEAD(void, GetMultisamplefv, GLenum pname, GLuint index, GLfloat* val) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetMultisamplefv, pname, index, val)
DECLARE_GL_FUNCTION_HEAD(void, SampleMaski, GLuint maskNumber, GLbitfield mask) DECLARE_GL_FUNCTION_END_NO_RETURN(void, SampleMaski, maskNumber, mask) DECLARE_GL_FUNCTION_HEAD(void, SampleMaski, GLuint maskNumber, GLbitfield mask) DECLARE_GL_FUNCTION_END_NO_RETURN(void, SampleMaski, maskNumber, mask)
DECLARE_GL_FUNCTION_HEAD(void, GetTexLevelParameteriv, GLenum target, GLint level, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTexLevelParameteriv, target, level, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetTexLevelParameteriv, GLenum target, GLint level, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTexLevelParameteriv, target, level, pname, params)
DECLARE_GL_FUNCTION_HEAD(void, GetTexLevelParameterfv, GLenum target, GLint level, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTexLevelParameterfv, target, level, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetTexLevelParameterfv, GLenum target, GLint level, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTexLevelParameterfv, target, level, pname, params)
@@ -418,7 +419,7 @@ DECLARE_GL_FUNCTION_HEAD(void, GetSamplerParameterIiv, GLuint sampler, GLenum pn
DECLARE_GL_FUNCTION_HEAD(void, GetSamplerParameterIuiv, GLuint sampler, GLenum pname, GLuint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetSamplerParameterIuiv, sampler, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetSamplerParameterIuiv, GLuint sampler, GLenum pname, GLuint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetSamplerParameterIuiv, sampler, pname, params)
DECLARE_GL_FUNCTION_HEAD(void, TexBuffer, GLenum target, GLenum internalformat, GLuint buffer) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexBuffer, target, internalformat, buffer) DECLARE_GL_FUNCTION_HEAD(void, TexBuffer, GLenum target, GLenum internalformat, GLuint buffer) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexBuffer, target, internalformat, buffer)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexBufferRange, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexBufferRange, target, internalformat, buffer, offset, size) DECLARE_GL_FUNCTION_STUB_HEAD(void, TexBufferRange, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexBufferRange, target, internalformat, buffer, offset, size)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexStorage3DMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexStorage3DMultisample, target, samples, internalformat, width, height, depth, fixedsamplelocations) DECLARE_GL_FUNCTION_HEAD(void, TexStorage3DMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexStorage3DMultisample, target, samples, internalformat, width, height, depth, fixedsamplelocations)
DECLARE_GL_FUNCTION_HEAD(void*, MapBufferRange, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) DECLARE_GL_FUNCTION_END(void*, MapBufferRange, target, offset, length, access) DECLARE_GL_FUNCTION_HEAD(void*, MapBufferRange, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) DECLARE_GL_FUNCTION_END(void*, MapBufferRange, target, offset, length, access)
DECLARE_GL_FUNCTION_STUB_HEAD(void, ClearIndex, GLfloat c) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClearIndex, c) DECLARE_GL_FUNCTION_STUB_HEAD(void, ClearIndex, GLfloat c) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClearIndex, c)
DECLARE_GL_FUNCTION_STUB_HEAD(void, IndexMask, GLuint mask) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, IndexMask, mask) DECLARE_GL_FUNCTION_STUB_HEAD(void, IndexMask, GLuint mask) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, IndexMask, mask)
@@ -830,8 +831,8 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib3sv, GLuint index, const GLshort
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4Nbv, GLuint index, const GLbyte* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4Nbv, index, v) DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4Nbv, GLuint index, const GLbyte* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4Nbv, index, v)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4Niv, GLuint index, const GLint* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4Niv, index, v) DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4Niv, GLuint index, const GLint* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4Niv, index, v)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4Nsv, GLuint index, const GLshort* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4Nsv, index, v) DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4Nsv, GLuint index, const GLshort* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4Nsv, index, v)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4Nub, GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4Nub, index, x, y, z, w) DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib4Nub, GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib4Nub, index, x, y, z, w)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4Nubv, GLuint index, const GLubyte* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4Nubv, index, v) DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib4Nubv, GLuint index, const GLubyte* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib4Nubv, index, v)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4Nuiv, GLuint index, const GLuint* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4Nuiv, index, v) DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4Nuiv, GLuint index, const GLuint* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4Nuiv, index, v)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4Nusv, GLuint index, const GLushort* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4Nusv, index, v) DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4Nusv, GLuint index, const GLushort* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4Nusv, index, v)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4bv, GLuint index, const GLbyte* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4bv, index, v) DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4bv, GLuint index, const GLbyte* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4bv, index, v)
@@ -840,11 +841,11 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4dv, GLuint index, const GLdoubl
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4iv, GLuint index, const GLint* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4iv, index, v) DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4iv, GLuint index, const GLint* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4iv, index, v)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4s, GLuint index, GLshort x, GLshort y, GLshort z, GLshort w) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4s, index, x, y, z, w) DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4s, GLuint index, GLshort x, GLshort y, GLshort z, GLshort w) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4s, index, x, y, z, w)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4sv, GLuint index, const GLshort* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4sv, index, v) DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4sv, GLuint index, const GLshort* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4sv, index, v)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4ubv, GLuint index, const GLubyte* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4ubv, index, v) DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib4ubv, GLuint index, const GLubyte* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib4ubv, index, v)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4uiv, GLuint index, const GLuint* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4uiv, index, v) DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4uiv, GLuint index, const GLuint* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4uiv, index, v)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4usv, GLuint index, const GLushort* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4usv, index, v) DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4usv, GLuint index, const GLushort* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4usv, index, v)
DECLARE_GL_FUNCTION_STUB_HEAD(void, PrimitiveRestartIndex, GLuint index) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, PrimitiveRestartIndex, index) DECLARE_GL_FUNCTION_STUB_HEAD(void, PrimitiveRestartIndex, GLuint index) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, PrimitiveRestartIndex, index)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetActiveUniformName, GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformName) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetActiveUniformName, program, uniformIndex, bufSize, length, uniformName) DECLARE_GL_FUNCTION_HEAD(void, GetActiveUniformName, GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformName) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetActiveUniformName, program, uniformIndex, bufSize, length, uniformName)
DECLARE_GL_FUNCTION_HEAD(void, MultiDrawElementsBaseVertex, GLenum mode, const GLsizei* count, GLenum type, const void* const* indices, GLsizei drawcount, const GLint* basevertex) DECLARE_GL_FUNCTION_END_NO_RETURN(void, MultiDrawElementsBaseVertex, mode, count, type, indices, drawcount, basevertex) DECLARE_GL_FUNCTION_HEAD(void, MultiDrawElementsBaseVertex, GLenum mode, const GLsizei* count, GLenum type, const void* const* indices, GLsizei drawcount, const GLint* basevertex) DECLARE_GL_FUNCTION_END_NO_RETURN(void, MultiDrawElementsBaseVertex, mode, count, type, indices, drawcount, basevertex)
DECLARE_GL_FUNCTION_HEAD(void, ProvokingVertex, GLenum mode) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProvokingVertex, mode) DECLARE_GL_FUNCTION_HEAD(void, ProvokingVertex, GLenum mode) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProvokingVertex, mode)
DECLARE_GL_FUNCTION_HEAD(void, TexImage2DMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexImage2DMultisample, target, samples, internalformat, width, height, fixedsamplelocations) DECLARE_GL_FUNCTION_HEAD(void, TexImage2DMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexImage2DMultisample, target, samples, internalformat, width, height, fixedsamplelocations)
@@ -1029,19 +1030,19 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, GetNamedFramebufferParameteriv, GLuint frame
DECLARE_GL_FUNCTION_HEAD(void, GetNamedFramebufferAttachmentParameteriv, GLuint framebuffer, GLenum attachment, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetNamedFramebufferAttachmentParameteriv, framebuffer, attachment, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetNamedFramebufferAttachmentParameteriv, GLuint framebuffer, GLenum attachment, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetNamedFramebufferAttachmentParameteriv, framebuffer, attachment, pname, params)
DECLARE_GL_FUNCTION_HEAD(void, CreateRenderbuffers, GLsizei n, GLuint* renderbuffers) DECLARE_GL_FUNCTION_END_NO_RETURN(void, CreateRenderbuffers, n, renderbuffers) DECLARE_GL_FUNCTION_HEAD(void, CreateRenderbuffers, GLsizei n, GLuint* renderbuffers) DECLARE_GL_FUNCTION_END_NO_RETURN(void, CreateRenderbuffers, n, renderbuffers)
DECLARE_GL_FUNCTION_HEAD(void, NamedRenderbufferStorage, GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, NamedRenderbufferStorage, renderbuffer, internalformat, width, height) DECLARE_GL_FUNCTION_HEAD(void, NamedRenderbufferStorage, GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, NamedRenderbufferStorage, renderbuffer, internalformat, width, height)
DECLARE_GL_FUNCTION_STUB_HEAD(void, NamedRenderbufferStorageMultisample, GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, NamedRenderbufferStorageMultisample, renderbuffer, samples, internalformat, width, height) DECLARE_GL_FUNCTION_HEAD(void, NamedRenderbufferStorageMultisample, GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, NamedRenderbufferStorageMultisample, renderbuffer, samples, internalformat, width, height)
DECLARE_GL_FUNCTION_HEAD(void, GetNamedRenderbufferParameteriv, GLuint renderbuffer, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetNamedRenderbufferParameteriv, renderbuffer, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetNamedRenderbufferParameteriv, GLuint renderbuffer, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetNamedRenderbufferParameteriv, renderbuffer, pname, params)
DECLARE_GL_FUNCTION_HEAD(void, CreateTextures, GLenum target, GLsizei n, GLuint* textures) DECLARE_GL_FUNCTION_END_NO_RETURN(void, CreateTextures, target, n, textures) DECLARE_GL_FUNCTION_HEAD(void, CreateTextures, GLenum target, GLsizei n, GLuint* textures) DECLARE_GL_FUNCTION_END_NO_RETURN(void, CreateTextures, target, n, textures)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureBuffer, GLuint texture, GLenum internalformat, GLuint buffer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureBuffer, texture, internalformat, buffer) DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureBuffer, GLuint texture, GLenum internalformat, GLuint buffer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureBuffer, texture, internalformat, buffer)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureBufferRange, GLuint texture, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureBufferRange, texture, internalformat, buffer, offset, size) DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureBufferRange, GLuint texture, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureBufferRange, texture, internalformat, buffer, offset, size)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureStorage1D, GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureStorage1D, texture, levels, internalformat, width) DECLARE_GL_FUNCTION_HEAD(void, TextureStorage1D, GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureStorage1D, texture, levels, internalformat, width)
DECLARE_GL_FUNCTION_HEAD(void, TextureStorage2D, GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureStorage2D, texture, levels, internalformat, width, height) DECLARE_GL_FUNCTION_HEAD(void, TextureStorage2D, GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureStorage2D, texture, levels, internalformat, width, height)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureStorage3D, GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureStorage3D, texture, levels, internalformat, width, height, depth) DECLARE_GL_FUNCTION_HEAD(void, TextureStorage3D, GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureStorage3D, texture, levels, internalformat, width, height, depth)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureStorage2DMultisample, GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureStorage2DMultisample, texture, samples, internalformat, width, height, fixedsamplelocations) DECLARE_GL_FUNCTION_HEAD(void, TextureStorage2DMultisample, GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureStorage2DMultisample, texture, samples, internalformat, width, height, fixedsamplelocations)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureStorage3DMultisample, GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureStorage3DMultisample, texture, samples, internalformat, width, height, depth, fixedsamplelocations) DECLARE_GL_FUNCTION_HEAD(void, TextureStorage3DMultisample, GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureStorage3DMultisample, texture, samples, internalformat, width, height, depth, fixedsamplelocations)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureSubImage1D, GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureSubImage1D, texture, level, xoffset, width, format, type, pixels) DECLARE_GL_FUNCTION_HEAD(void, TextureSubImage1D, GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureSubImage1D, texture, level, xoffset, width, format, type, pixels)
DECLARE_GL_FUNCTION_HEAD(void, TextureSubImage2D, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureSubImage2D, texture, level, xoffset, yoffset, width, height, format, type, pixels) DECLARE_GL_FUNCTION_HEAD(void, TextureSubImage2D, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureSubImage2D, texture, level, xoffset, yoffset, width, height, format, type, pixels)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureSubImage3D, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureSubImage3D, texture, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels) DECLARE_GL_FUNCTION_HEAD(void, TextureSubImage3D, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureSubImage3D, texture, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels)
DECLARE_GL_FUNCTION_STUB_HEAD(void, CompressedTextureSubImage1D, GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CompressedTextureSubImage1D, texture, level, xoffset, width, format, imageSize, data) DECLARE_GL_FUNCTION_STUB_HEAD(void, CompressedTextureSubImage1D, GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CompressedTextureSubImage1D, texture, level, xoffset, width, format, imageSize, data)
DECLARE_GL_FUNCTION_STUB_HEAD(void, CompressedTextureSubImage2D, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CompressedTextureSubImage2D, texture, level, xoffset, yoffset, width, height, format, imageSize, data) DECLARE_GL_FUNCTION_STUB_HEAD(void, CompressedTextureSubImage2D, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CompressedTextureSubImage2D, texture, level, xoffset, yoffset, width, height, format, imageSize, data)
DECLARE_GL_FUNCTION_STUB_HEAD(void, CompressedTextureSubImage3D, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CompressedTextureSubImage3D, texture, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data) DECLARE_GL_FUNCTION_STUB_HEAD(void, CompressedTextureSubImage3D, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CompressedTextureSubImage3D, texture, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data)
@@ -1049,20 +1050,20 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTextureSubImage1D, GLuint texture, GLint
DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTextureSubImage2D, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyTextureSubImage2D, texture, level, xoffset, yoffset, x, y, width, height) DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTextureSubImage2D, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyTextureSubImage2D, texture, level, xoffset, yoffset, x, y, width, height)
DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTextureSubImage3D, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyTextureSubImage3D, texture, level, xoffset, yoffset, zoffset, x, y, width, height) DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTextureSubImage3D, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyTextureSubImage3D, texture, level, xoffset, yoffset, zoffset, x, y, width, height)
DECLARE_GL_FUNCTION_HEAD(void, TextureParameterf, GLuint texture, GLenum pname, GLfloat param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureParameterf, texture, pname, param) DECLARE_GL_FUNCTION_HEAD(void, TextureParameterf, GLuint texture, GLenum pname, GLfloat param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureParameterf, texture, pname, param)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureParameterfv, GLuint texture, GLenum pname, const GLfloat* param) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureParameterfv, texture, pname, param) DECLARE_GL_FUNCTION_HEAD(void, TextureParameterfv, GLuint texture, GLenum pname, const GLfloat* param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureParameterfv, texture, pname, param)
DECLARE_GL_FUNCTION_HEAD(void, TextureParameteri, GLuint texture, GLenum pname, GLint param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureParameteri, texture, pname, param) DECLARE_GL_FUNCTION_HEAD(void, TextureParameteri, GLuint texture, GLenum pname, GLint param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureParameteri, texture, pname, param)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureParameterIiv, GLuint texture, GLenum pname, const GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureParameterIiv, texture, pname, params) DECLARE_GL_FUNCTION_HEAD(void, TextureParameterIiv, GLuint texture, GLenum pname, const GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureParameterIiv, texture, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureParameterIuiv, GLuint texture, GLenum pname, const GLuint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureParameterIuiv, texture, pname, params) DECLARE_GL_FUNCTION_HEAD(void, TextureParameterIuiv, GLuint texture, GLenum pname, const GLuint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureParameterIuiv, texture, pname, params)
DECLARE_GL_FUNCTION_HEAD(void, TextureParameteriv, GLuint texture, GLenum pname, const GLint* param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureParameteriv, texture, pname, param) DECLARE_GL_FUNCTION_HEAD(void, TextureParameteriv, GLuint texture, GLenum pname, const GLint* param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureParameteriv, texture, pname, param)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GenerateTextureMipmap, GLuint texture) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GenerateTextureMipmap, texture) DECLARE_GL_FUNCTION_HEAD(void, GenerateTextureMipmap, GLuint texture) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GenerateTextureMipmap, texture)
DECLARE_GL_FUNCTION_HEAD(void, BindTextureUnit, GLuint unit, GLuint texture) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BindTextureUnit, unit, texture) DECLARE_GL_FUNCTION_HEAD(void, BindTextureUnit, GLuint unit, GLuint texture) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BindTextureUnit, unit, texture)
DECLARE_GL_FUNCTION_HEAD(void, GetTextureImage, GLuint texture, GLint level, GLenum format, GLenum type, GLsizei bufSize, void* pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureImage, texture, level, format, type, bufSize, pixels) DECLARE_GL_FUNCTION_HEAD(void, GetTextureImage, GLuint texture, GLint level, GLenum format, GLenum type, GLsizei bufSize, void* pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureImage, texture, level, format, type, bufSize, pixels)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetCompressedTextureImage, GLuint texture, GLint level, GLsizei bufSize, void* pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetCompressedTextureImage, texture, level, bufSize, pixels) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetCompressedTextureImage, GLuint texture, GLint level, GLsizei bufSize, void* pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetCompressedTextureImage, texture, level, bufSize, pixels)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetTextureLevelParameterfv, GLuint texture, GLint level, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTextureLevelParameterfv, texture, level, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetTextureLevelParameterfv, GLuint texture, GLint level, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureLevelParameterfv, texture, level, pname, params)
DECLARE_GL_FUNCTION_HEAD(void, GetTextureLevelParameteriv, GLuint texture, GLint level, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureLevelParameteriv, texture, level, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetTextureLevelParameteriv, GLuint texture, GLint level, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureLevelParameteriv, texture, level, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetTextureParameterfv, GLuint texture, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTextureParameterfv, texture, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetTextureParameterfv, GLuint texture, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureParameterfv, texture, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetTextureParameterIiv, GLuint texture, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTextureParameterIiv, texture, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetTextureParameterIiv, GLuint texture, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureParameterIiv, texture, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetTextureParameterIuiv, GLuint texture, GLenum pname, GLuint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTextureParameterIuiv, texture, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetTextureParameterIuiv, GLuint texture, GLenum pname, GLuint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureParameterIuiv, texture, pname, params)
DECLARE_GL_FUNCTION_HEAD(void, GetTextureParameteriv, GLuint texture, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureParameteriv, texture, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetTextureParameteriv, GLuint texture, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureParameteriv, texture, pname, params)
DECLARE_GL_FUNCTION_HEAD(void, CreateVertexArrays, GLsizei n, GLuint* arrays) DECLARE_GL_FUNCTION_END_NO_RETURN(void, CreateVertexArrays, n, arrays) DECLARE_GL_FUNCTION_HEAD(void, CreateVertexArrays, GLsizei n, GLuint* arrays) DECLARE_GL_FUNCTION_END_NO_RETURN(void, CreateVertexArrays, n, arrays)
DECLARE_GL_FUNCTION_HEAD(void, DisableVertexArrayAttrib, GLuint vaobj, GLuint index) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DisableVertexArrayAttrib, vaobj, index) DECLARE_GL_FUNCTION_HEAD(void, DisableVertexArrayAttrib, GLuint vaobj, GLuint index) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DisableVertexArrayAttrib, vaobj, index)
@@ -1490,9 +1491,9 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, Vertex3xvOES, const GLfixed* coords) DECLARE
DECLARE_GL_FUNCTION_STUB_HEAD(void, Vertex4xOES, GLfixed x, GLfixed y, GLfixed z) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Vertex4xOES, x, y, z) DECLARE_GL_FUNCTION_STUB_HEAD(void, Vertex4xOES, GLfixed x, GLfixed y, GLfixed z) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Vertex4xOES, x, y, z)
DECLARE_GL_FUNCTION_STUB_HEAD(void, Vertex4xvOES, const GLfixed* coords) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Vertex4xvOES, coords) DECLARE_GL_FUNCTION_STUB_HEAD(void, Vertex4xvOES, const GLfixed* coords) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Vertex4xvOES, coords)
DECLARE_GL_FUNCTION_STUB_HEAD(GLbitfield, QueryMatrixxOES, GLfixed* mantissa, GLint* exponent) DECLARE_GL_FUNCTION_STUB_END(GLbitfield, QueryMatrixxOES, mantissa, exponent) DECLARE_GL_FUNCTION_STUB_HEAD(GLbitfield, QueryMatrixxOES, GLfixed* mantissa, GLint* exponent) DECLARE_GL_FUNCTION_STUB_END(GLbitfield, QueryMatrixxOES, mantissa, exponent)
DECLARE_GL_FUNCTION_STUB_HEAD(void, ClearDepthfOES, GLclampf depth) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClearDepthfOES, depth) DECLARE_GL_FUNCTION_HEAD(void, ClearDepthfOES, GLclampf depth) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ClearDepth, static_cast<GLclampd>(depth))
DECLARE_GL_FUNCTION_STUB_HEAD(void, ClipPlanefOES, GLenum plane, const GLfloat* equation) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClipPlanefOES, plane, equation) DECLARE_GL_FUNCTION_STUB_HEAD(void, ClipPlanefOES, GLenum plane, const GLfloat* equation) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClipPlanefOES, plane, equation)
DECLARE_GL_FUNCTION_STUB_HEAD(void, DepthRangefOES, GLclampf n, GLclampf f) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DepthRangefOES, n, f) DECLARE_GL_FUNCTION_HEAD(void, DepthRangefOES, GLclampf n, GLclampf f) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DepthRange, static_cast<GLclampd>(n), static_cast<GLclampd>(f))
DECLARE_GL_FUNCTION_STUB_HEAD(void, FrustumfOES, GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, FrustumfOES, l, r, b, t, n, f) DECLARE_GL_FUNCTION_STUB_HEAD(void, FrustumfOES, GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, FrustumfOES, l, r, b, t, n, f)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetClipPlanefOES, GLenum plane, GLfloat* equation) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetClipPlanefOES, plane, equation) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetClipPlanefOES, GLenum plane, GLfloat* equation) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetClipPlanefOES, plane, equation)
DECLARE_GL_FUNCTION_STUB_HEAD(void, OrthofOES, GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, OrthofOES, l, r, b, t, n, f) DECLARE_GL_FUNCTION_STUB_HEAD(void, OrthofOES, GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, OrthofOES, l, r, b, t, n, f)
@@ -1760,25 +1761,25 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, MatrixPopEXT, GLenum mode) DECLARE_GL_FUNCTI
DECLARE_GL_FUNCTION_STUB_HEAD(void, MatrixPushEXT, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, MatrixPushEXT, mode) DECLARE_GL_FUNCTION_STUB_HEAD(void, MatrixPushEXT, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, MatrixPushEXT, mode)
DECLARE_GL_FUNCTION_STUB_HEAD(void, ClientAttribDefaultEXT, GLbitfield mask) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClientAttribDefaultEXT, mask) DECLARE_GL_FUNCTION_STUB_HEAD(void, ClientAttribDefaultEXT, GLbitfield mask) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClientAttribDefaultEXT, mask)
DECLARE_GL_FUNCTION_STUB_HEAD(void, PushClientAttribDefaultEXT, GLbitfield mask) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, PushClientAttribDefaultEXT, mask) DECLARE_GL_FUNCTION_STUB_HEAD(void, PushClientAttribDefaultEXT, GLbitfield mask) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, PushClientAttribDefaultEXT, mask)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureParameterfEXT, GLuint texture, GLenum target, GLenum pname, GLfloat param) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureParameterfEXT, texture, target, pname, param) DECLARE_GL_FUNCTION_HEAD(void, TextureParameterfEXT, GLuint texture, GLenum target, GLenum pname, GLfloat param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureParameterf, texture, pname, param)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureParameterfvEXT, GLuint texture, GLenum target, GLenum pname, const GLfloat* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureParameterfvEXT, texture, target, pname, params) DECLARE_GL_FUNCTION_HEAD(void, TextureParameterfvEXT, GLuint texture, GLenum target, GLenum pname, const GLfloat* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureParameterfv, texture, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureParameteriEXT, GLuint texture, GLenum target, GLenum pname, GLint param) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureParameteriEXT, texture, target, pname, param) DECLARE_GL_FUNCTION_HEAD(void, TextureParameteriEXT, GLuint texture, GLenum target, GLenum pname, GLint param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureParameteri, texture, pname, param)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureParameterivEXT, GLuint texture, GLenum target, GLenum pname, const GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureParameterivEXT, texture, target, pname, params) DECLARE_GL_FUNCTION_HEAD(void, TextureParameterivEXT, GLuint texture, GLenum target, GLenum pname, const GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureParameteriv, texture, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureImage1DEXT, GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureImage1DEXT, texture, target, level, internalformat, width, border, format, type, pixels) DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureImage1DEXT, GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureImage1DEXT, texture, target, level, internalformat, width, border, format, type, pixels)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureImage2DEXT, GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureImage2DEXT, texture, target, level, internalformat, width, height, border, format, type, pixels) DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureImage2DEXT, GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureImage2DEXT, texture, target, level, internalformat, width, height, border, format, type, pixels)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureSubImage1DEXT, GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureSubImage1DEXT, texture, target, level, xoffset, width, format, type, pixels) DECLARE_GL_FUNCTION_HEAD(void, TextureSubImage1DEXT, GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureSubImage1D, texture, level, xoffset, width, format, type, pixels)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureSubImage2DEXT, GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureSubImage2DEXT, texture, target, level, xoffset, yoffset, width, height, format, type, pixels) DECLARE_GL_FUNCTION_HEAD(void, TextureSubImage2DEXT, GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureSubImage2D, texture, level, xoffset, yoffset, width, height, format, type, pixels)
DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTextureImage1DEXT, GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyTextureImage1DEXT, texture, target, level, internalformat, x, y, width, border) DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTextureImage1DEXT, GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyTextureImage1DEXT, texture, target, level, internalformat, x, y, width, border)
DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTextureImage2DEXT, GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyTextureImage2DEXT, texture, target, level, internalformat, x, y, width, height, border) DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTextureImage2DEXT, GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyTextureImage2DEXT, texture, target, level, internalformat, x, y, width, height, border)
DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTextureSubImage1DEXT, GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyTextureSubImage1DEXT, texture, target, level, xoffset, x, y, width) DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTextureSubImage1DEXT, GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyTextureSubImage1DEXT, texture, target, level, xoffset, x, y, width)
DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTextureSubImage2DEXT, GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyTextureSubImage2DEXT, texture, target, level, xoffset, yoffset, x, y, width, height) DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTextureSubImage2DEXT, GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyTextureSubImage2DEXT, texture, target, level, xoffset, yoffset, x, y, width, height)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetTextureImageEXT, GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, void* pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTextureImageEXT, texture, target, level, format, type, pixels) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetTextureImageEXT, GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, void* pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTextureImageEXT, texture, target, level, format, type, pixels)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetTextureParameterfvEXT, GLuint texture, GLenum target, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTextureParameterfvEXT, texture, target, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetTextureParameterfvEXT, GLuint texture, GLenum target, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureParameterfv, texture, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetTextureParameterivEXT, GLuint texture, GLenum target, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTextureParameterivEXT, texture, target, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetTextureParameterivEXT, GLuint texture, GLenum target, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureParameteriv, texture, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetTextureLevelParameterfvEXT, GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTextureLevelParameterfvEXT, texture, target, level, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetTextureLevelParameterfvEXT, GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureLevelParameterfv, texture, level, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetTextureLevelParameterivEXT, GLuint texture, GLenum target, GLint level, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTextureLevelParameterivEXT, texture, target, level, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetTextureLevelParameterivEXT, GLuint texture, GLenum target, GLint level, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureLevelParameteriv, texture, level, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureImage3DEXT, GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureImage3DEXT, texture, target, level, internalformat, width, height, depth, border, format, type, pixels) DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureImage3DEXT, GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureImage3DEXT, texture, target, level, internalformat, width, height, depth, border, format, type, pixels)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureSubImage3DEXT, GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureSubImage3DEXT, texture, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels) DECLARE_GL_FUNCTION_HEAD(void, TextureSubImage3DEXT, GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureSubImage3D, texture, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels)
DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTextureSubImage3DEXT, GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyTextureSubImage3DEXT, texture, target, level, xoffset, yoffset, zoffset, x, y, width, height) DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTextureSubImage3DEXT, GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyTextureSubImage3DEXT, texture, target, level, xoffset, yoffset, zoffset, x, y, width, height)
DECLARE_GL_FUNCTION_STUB_HEAD(void, BindMultiTextureEXT, GLenum texunit, GLenum target, GLuint texture) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BindMultiTextureEXT, texunit, target, texture) DECLARE_GL_FUNCTION_STUB_HEAD(void, BindMultiTextureEXT, GLenum texunit, GLenum target, GLuint texture) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BindMultiTextureEXT, texunit, target, texture)
DECLARE_GL_FUNCTION_STUB_HEAD(void, MultiTexCoordPointerEXT, GLenum texunit, GLint size, GLenum type, GLsizei stride, const void* pointer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, MultiTexCoordPointerEXT, texunit, size, type, stride, pointer) DECLARE_GL_FUNCTION_STUB_HEAD(void, MultiTexCoordPointerEXT, GLenum texunit, GLint size, GLenum type, GLsizei stride, const void* pointer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, MultiTexCoordPointerEXT, texunit, size, type, stride, pointer)
@@ -1853,10 +1854,10 @@ DECLARE_GL_FUNCTION_HEAD(void, GetNamedBufferPointervEXT, GLuint buffer, GLenum
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetNamedBufferSubDataEXT, GLuint buffer, GLintptr offset, GLsizeiptr size, void* data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetNamedBufferSubDataEXT, buffer, offset, size, data) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetNamedBufferSubDataEXT, GLuint buffer, GLintptr offset, GLsizeiptr size, void* data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetNamedBufferSubDataEXT, buffer, offset, size, data)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureBufferEXT, GLuint texture, GLenum target, GLenum internalformat, GLuint buffer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureBufferEXT, texture, target, internalformat, buffer) DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureBufferEXT, GLuint texture, GLenum target, GLenum internalformat, GLuint buffer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureBufferEXT, texture, target, internalformat, buffer)
DECLARE_GL_FUNCTION_STUB_HEAD(void, MultiTexBufferEXT, GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, MultiTexBufferEXT, texunit, target, internalformat, buffer) DECLARE_GL_FUNCTION_STUB_HEAD(void, MultiTexBufferEXT, GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, MultiTexBufferEXT, texunit, target, internalformat, buffer)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureParameterIivEXT, GLuint texture, GLenum target, GLenum pname, const GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureParameterIivEXT, texture, target, pname, params) DECLARE_GL_FUNCTION_HEAD(void, TextureParameterIivEXT, GLuint texture, GLenum target, GLenum pname, const GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureParameterIiv, texture, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureParameterIuivEXT, GLuint texture, GLenum target, GLenum pname, const GLuint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureParameterIuivEXT, texture, target, pname, params) DECLARE_GL_FUNCTION_HEAD(void, TextureParameterIuivEXT, GLuint texture, GLenum target, GLenum pname, const GLuint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureParameterIuiv, texture, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetTextureParameterIivEXT, GLuint texture, GLenum target, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTextureParameterIivEXT, texture, target, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetTextureParameterIivEXT, GLuint texture, GLenum target, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureParameterIiv, texture, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetTextureParameterIuivEXT, GLuint texture, GLenum target, GLenum pname, GLuint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTextureParameterIuivEXT, texture, target, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetTextureParameterIuivEXT, GLuint texture, GLenum target, GLenum pname, GLuint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureParameterIuiv, texture, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, MultiTexParameterIivEXT, GLenum texunit, GLenum target, GLenum pname, const GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, MultiTexParameterIivEXT, texunit, target, pname, params) DECLARE_GL_FUNCTION_STUB_HEAD(void, MultiTexParameterIivEXT, GLenum texunit, GLenum target, GLenum pname, const GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, MultiTexParameterIivEXT, texunit, target, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, MultiTexParameterIuivEXT, GLenum texunit, GLenum target, GLenum pname, const GLuint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, MultiTexParameterIuivEXT, texunit, target, pname, params) DECLARE_GL_FUNCTION_STUB_HEAD(void, MultiTexParameterIuivEXT, GLenum texunit, GLenum target, GLenum pname, const GLuint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, MultiTexParameterIuivEXT, texunit, target, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetMultiTexParameterIivEXT, GLenum texunit, GLenum target, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetMultiTexParameterIivEXT, texunit, target, pname, params) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetMultiTexParameterIivEXT, GLenum texunit, GLenum target, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetMultiTexParameterIivEXT, texunit, target, pname, params)
@@ -1886,7 +1887,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, GetNamedProgramivEXT, GLuint program, GLenum
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetNamedProgramStringEXT, GLuint program, GLenum target, GLenum pname, void* string) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetNamedProgramStringEXT, program, target, pname, string) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetNamedProgramStringEXT, GLuint program, GLenum target, GLenum pname, void* string) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetNamedProgramStringEXT, program, target, pname, string)
DECLARE_GL_FUNCTION_HEAD(void, NamedRenderbufferStorageEXT, GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, NamedRenderbufferStorage, renderbuffer, internalformat, width, height) DECLARE_GL_FUNCTION_HEAD(void, NamedRenderbufferStorageEXT, GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, NamedRenderbufferStorage, renderbuffer, internalformat, width, height)
DECLARE_GL_FUNCTION_HEAD(void, GetNamedRenderbufferParameterivEXT, GLuint renderbuffer, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetNamedRenderbufferParameteriv, renderbuffer, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetNamedRenderbufferParameterivEXT, GLuint renderbuffer, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetNamedRenderbufferParameteriv, renderbuffer, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, NamedRenderbufferStorageMultisampleEXT, GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, NamedRenderbufferStorageMultisampleEXT, renderbuffer, samples, internalformat, width, height) DECLARE_GL_FUNCTION_HEAD(void, NamedRenderbufferStorageMultisampleEXT, GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, NamedRenderbufferStorageMultisample, renderbuffer, samples, internalformat, width, height)
DECLARE_GL_FUNCTION_STUB_HEAD(void, NamedRenderbufferStorageMultisampleCoverageEXT, GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, NamedRenderbufferStorageMultisampleCoverageEXT, renderbuffer, coverageSamples, colorSamples, internalformat, width, height) DECLARE_GL_FUNCTION_STUB_HEAD(void, NamedRenderbufferStorageMultisampleCoverageEXT, GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, NamedRenderbufferStorageMultisampleCoverageEXT, renderbuffer, coverageSamples, colorSamples, internalformat, width, height)
DECLARE_GL_FUNCTION_STUB_HEAD(GLenum, CheckNamedFramebufferStatusEXT, GLuint framebuffer, GLenum target) DECLARE_GL_FUNCTION_STUB_END(GLenum, CheckNamedFramebufferStatusEXT, framebuffer, target) DECLARE_GL_FUNCTION_STUB_HEAD(GLenum, CheckNamedFramebufferStatusEXT, GLuint framebuffer, GLenum target) DECLARE_GL_FUNCTION_STUB_END(GLenum, CheckNamedFramebufferStatusEXT, framebuffer, target)
DECLARE_GL_FUNCTION_STUB_HEAD(void, NamedFramebufferTexture1DEXT, GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, NamedFramebufferTexture1DEXT, framebuffer, attachment, textarget, texture, level) DECLARE_GL_FUNCTION_STUB_HEAD(void, NamedFramebufferTexture1DEXT, GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, NamedFramebufferTexture1DEXT, framebuffer, attachment, textarget, texture, level)
@@ -1894,7 +1895,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, NamedFramebufferTexture2DEXT, GLuint framebu
DECLARE_GL_FUNCTION_STUB_HEAD(void, NamedFramebufferTexture3DEXT, GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, NamedFramebufferTexture3DEXT, framebuffer, attachment, textarget, texture, level, zoffset) DECLARE_GL_FUNCTION_STUB_HEAD(void, NamedFramebufferTexture3DEXT, GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, NamedFramebufferTexture3DEXT, framebuffer, attachment, textarget, texture, level, zoffset)
DECLARE_GL_FUNCTION_HEAD(void, NamedFramebufferRenderbufferEXT, GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) DECLARE_GL_FUNCTION_END_NO_RETURN(void, NamedFramebufferRenderbuffer, framebuffer, attachment, renderbuffertarget, renderbuffer) DECLARE_GL_FUNCTION_HEAD(void, NamedFramebufferRenderbufferEXT, GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) DECLARE_GL_FUNCTION_END_NO_RETURN(void, NamedFramebufferRenderbuffer, framebuffer, attachment, renderbuffertarget, renderbuffer)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetNamedFramebufferAttachmentParameterivEXT, GLuint framebuffer, GLenum attachment, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetNamedFramebufferAttachmentParameterivEXT, framebuffer, attachment, pname, params) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetNamedFramebufferAttachmentParameterivEXT, GLuint framebuffer, GLenum attachment, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetNamedFramebufferAttachmentParameterivEXT, framebuffer, attachment, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GenerateTextureMipmapEXT, GLuint texture, GLenum target) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GenerateTextureMipmapEXT, texture, target) DECLARE_GL_FUNCTION_HEAD(void, GenerateTextureMipmapEXT, GLuint texture, GLenum target) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GenerateTextureMipmap, texture)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GenerateMultiTexMipmapEXT, GLenum texunit, GLenum target) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GenerateMultiTexMipmapEXT, texunit, target) DECLARE_GL_FUNCTION_STUB_HEAD(void, GenerateMultiTexMipmapEXT, GLenum texunit, GLenum target) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GenerateMultiTexMipmapEXT, texunit, target)
DECLARE_GL_FUNCTION_STUB_HEAD(void, FramebufferDrawBufferEXT, GLuint framebuffer, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, FramebufferDrawBufferEXT, framebuffer, mode) DECLARE_GL_FUNCTION_STUB_HEAD(void, FramebufferDrawBufferEXT, GLuint framebuffer, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, FramebufferDrawBufferEXT, framebuffer, mode)
DECLARE_GL_FUNCTION_STUB_HEAD(void, FramebufferDrawBuffersEXT, GLuint framebuffer, GLsizei n, const GLenum* bufs) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, FramebufferDrawBuffersEXT, framebuffer, n, bufs) DECLARE_GL_FUNCTION_STUB_HEAD(void, FramebufferDrawBuffersEXT, GLuint framebuffer, GLsizei n, const GLenum* bufs) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, FramebufferDrawBuffersEXT, framebuffer, n, bufs)
@@ -1948,11 +1949,11 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniformMatrix3x4dvEXT, GLuint program
DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniformMatrix4x2dvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniformMatrix4x2dvEXT, program, location, count, transpose, value) DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniformMatrix4x2dvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniformMatrix4x2dvEXT, program, location, count, transpose, value)
DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniformMatrix4x3dvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniformMatrix4x3dvEXT, program, location, count, transpose, value) DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniformMatrix4x3dvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniformMatrix4x3dvEXT, program, location, count, transpose, value)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureBufferRangeEXT, GLuint texture, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureBufferRangeEXT, texture, target, internalformat, buffer, offset, size) DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureBufferRangeEXT, GLuint texture, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureBufferRangeEXT, texture, target, internalformat, buffer, offset, size)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureStorage1DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureStorage1DEXT, texture, target, levels, internalformat, width) DECLARE_GL_FUNCTION_HEAD(void, TextureStorage1DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureStorage1D, texture, levels, internalformat, width)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureStorage2DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureStorage2DEXT, texture, target, levels, internalformat, width, height) DECLARE_GL_FUNCTION_HEAD(void, TextureStorage2DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureStorage2D, texture, levels, internalformat, width, height)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureStorage3DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureStorage3DEXT, texture, target, levels, internalformat, width, height, depth) DECLARE_GL_FUNCTION_HEAD(void, TextureStorage3DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureStorage3D, texture, levels, internalformat, width, height, depth)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureStorage2DMultisampleEXT, GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureStorage2DMultisampleEXT, texture, target, samples, internalformat, width, height, fixedsamplelocations) DECLARE_GL_FUNCTION_HEAD(void, TextureStorage2DMultisampleEXT, GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureStorage2DMultisample, texture, samples, internalformat, width, height, fixedsamplelocations)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureStorage3DMultisampleEXT, GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureStorage3DMultisampleEXT, texture, target, samples, internalformat, width, height, depth, fixedsamplelocations) DECLARE_GL_FUNCTION_HEAD(void, TextureStorage3DMultisampleEXT, GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureStorage3DMultisample, texture, samples, internalformat, width, height, depth, fixedsamplelocations)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexArrayBindVertexBufferEXT, GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexArrayBindVertexBufferEXT, vaobj, bindingindex, buffer, offset, stride) DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexArrayBindVertexBufferEXT, GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexArrayBindVertexBufferEXT, vaobj, bindingindex, buffer, offset, stride)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexArrayVertexAttribFormatEXT, GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexArrayVertexAttribFormatEXT, vaobj, attribindex, size, type, normalized, relativeoffset) DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexArrayVertexAttribFormatEXT, GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexArrayVertexAttribFormatEXT, vaobj, attribindex, size, type, normalized, relativeoffset)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexArrayVertexAttribIFormatEXT, GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexArrayVertexAttribIFormatEXT, vaobj, attribindex, size, type, relativeoffset) DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexArrayVertexAttribIFormatEXT, GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexArrayVertexAttribIFormatEXT, vaobj, attribindex, size, type, relativeoffset)
@@ -2086,7 +2087,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, ClearColorIuiEXT, GLuint red, GLuint green,
DECLARE_GL_FUNCTION_STUB_HEAD(GLboolean, AreTexturesResidentEXT, GLsizei n, const GLuint* textures, GLboolean* residences) DECLARE_GL_FUNCTION_STUB_END(GLboolean, AreTexturesResidentEXT, n, textures, residences) DECLARE_GL_FUNCTION_STUB_HEAD(GLboolean, AreTexturesResidentEXT, GLsizei n, const GLuint* textures, GLboolean* residences) DECLARE_GL_FUNCTION_STUB_END(GLboolean, AreTexturesResidentEXT, n, textures, residences)
DECLARE_GL_FUNCTION_STUB_HEAD(void, PrioritizeTexturesEXT, GLsizei n, const GLuint* textures, const GLclampf* priorities) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, PrioritizeTexturesEXT, n, textures, priorities) DECLARE_GL_FUNCTION_STUB_HEAD(void, PrioritizeTexturesEXT, GLsizei n, const GLuint* textures, const GLclampf* priorities) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, PrioritizeTexturesEXT, n, textures, priorities)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureNormalEXT, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureNormalEXT, mode) DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureNormalEXT, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureNormalEXT, mode)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexStorage1DEXT, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexStorage1DEXT, target, levels, internalformat, width) DECLARE_GL_FUNCTION_HEAD(void, TexStorage1DEXT, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexStorage1D, target, levels, internalformat, width)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetQueryObjecti64vEXT, GLuint id, GLenum pname, GLint64* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetQueryObjecti64vEXT, id, pname, params) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetQueryObjecti64vEXT, GLuint id, GLenum pname, GLint64* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetQueryObjecti64vEXT, id, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetQueryObjectui64vEXT, GLuint id, GLenum pname, GLuint64* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetQueryObjectui64vEXT, id, pname, params) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetQueryObjectui64vEXT, GLuint id, GLenum pname, GLuint64* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetQueryObjectui64vEXT, id, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, BindBufferOffsetEXT, GLenum target, GLuint index, GLuint buffer, GLintptr offset) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BindBufferOffsetEXT, target, index, buffer, offset) DECLARE_GL_FUNCTION_STUB_HEAD(void, BindBufferOffsetEXT, GLenum target, GLuint index, GLuint buffer, GLintptr offset) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BindBufferOffsetEXT, target, index, buffer, offset)
@@ -2297,7 +2298,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, GetMapParameterfvNV, GLenum target, GLenum p
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetMapAttribParameterivNV, GLenum target, GLuint index, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetMapAttribParameterivNV, target, index, pname, params) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetMapAttribParameterivNV, GLenum target, GLuint index, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetMapAttribParameterivNV, target, index, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetMapAttribParameterfvNV, GLenum target, GLuint index, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetMapAttribParameterfvNV, target, index, pname, params) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetMapAttribParameterfvNV, GLenum target, GLuint index, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetMapAttribParameterfvNV, target, index, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, EvalMapsNV, GLenum target, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, EvalMapsNV, target, mode) DECLARE_GL_FUNCTION_STUB_HEAD(void, EvalMapsNV, GLenum target, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, EvalMapsNV, target, mode)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetMultisamplefvNV, GLenum pname, GLuint index, GLfloat* val) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetMultisamplefvNV, pname, index, val) DECLARE_GL_FUNCTION_HEAD(void, GetMultisamplefvNV, GLenum pname, GLuint index, GLfloat* val) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetMultisamplefv, pname, index, val)
DECLARE_GL_FUNCTION_STUB_HEAD(void, SampleMaskIndexedNV, GLuint index, GLbitfield mask) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, SampleMaskIndexedNV, index, mask) DECLARE_GL_FUNCTION_STUB_HEAD(void, SampleMaskIndexedNV, GLuint index, GLbitfield mask) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, SampleMaskIndexedNV, index, mask)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexRenderbufferNV, GLenum target, GLuint renderbuffer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexRenderbufferNV, target, renderbuffer) DECLARE_GL_FUNCTION_STUB_HEAD(void, TexRenderbufferNV, GLenum target, GLuint renderbuffer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexRenderbufferNV, target, renderbuffer)
DECLARE_GL_FUNCTION_STUB_HEAD(void, DeleteFencesNV, GLsizei n, const GLuint* fences) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DeleteFencesNV, n, fences) DECLARE_GL_FUNCTION_STUB_HEAD(void, DeleteFencesNV, GLsizei n, const GLuint* fences) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DeleteFencesNV, n, fences)
@@ -15,10 +15,144 @@
#include <MG_State/GLState/ErrorState/Error.h> #include <MG_State/GLState/ErrorState/Error.h>
#include <MG_Util/Converters/GLToStr/GLEnumConverter.h> #include <MG_Util/Converters/GLToStr/GLEnumConverter.h>
#include <MG_Util/Converters/GLToMG/TextureEnumConverter.h> #include <MG_Util/Converters/GLToMG/TextureEnumConverter.h>
#include <MG_Util/Converters/MGToMG/TextureEnumConverter.h>
#include <MG_Util/Converters/MGToGL/TextureEnumConverter.h> #include <MG_Util/Converters/MGToGL/TextureEnumConverter.h>
#include <MG_Util/Converters/MGToStr/TextureEnumConverter.h>
#include <MG_Util/Converters/GLToMG/FramebufferEnumConverter.h> #include <MG_Util/Converters/GLToMG/FramebufferEnumConverter.h>
namespace MobileGL::MG_Impl::GLImpl { namespace MobileGL::MG_Impl::GLImpl {
namespace {
Bool IsActiveBackendDirectVulkan() {
auto* activeBackend = MG_Backend::pActiveBackendObject.get();
return activeBackend != nullptr && activeBackend->GetBackendType() == BackendType::DirectVulkan;
}
Bool HasDistinctCompleteDepthStencilTextureAttachments(
const MG_State::GLState::FramebufferObject& framebufferObject) {
if (framebufferObject.GetExternalIndex() == 0) {
return false;
}
const auto& depthAttachment = framebufferObject.GetAttachment(FramebufferAttachmentType::Depth);
const auto& stencilAttachment = framebufferObject.GetAttachment(FramebufferAttachmentType::Stencil);
if (!depthAttachment.IsComplete() || !stencilAttachment.IsComplete() ||
!depthAttachment.IsTexture() || !stencilAttachment.IsTexture()) {
return false;
}
return depthAttachment.GetTexture().get() != stencilAttachment.GetTexture().get() ||
depthAttachment.GetTextureUploadTarget() != stencilAttachment.GetTextureUploadTarget() ||
depthAttachment.GetTextureLevel() != stencilAttachment.GetTextureLevel();
}
Bool HasCompleteRenderbufferAttachment(const MG_State::GLState::FramebufferObject& framebufferObject) {
if (framebufferObject.GetExternalIndex() == 0) {
return false;
}
for (const auto& attachment : framebufferObject.GetAllAttachmentObjects()) {
if (attachment.IsRenderbuffer() && attachment.IsComplete()) {
return true;
}
}
return false;
}
Bool IsUnsupportedFramebufferForDirectVulkan(
const MG_State::GLState::FramebufferObject& framebufferObject) {
return HasDistinctCompleteDepthStencilTextureAttachments(framebufferObject) ||
HasCompleteRenderbufferAttachment(framebufferObject);
}
void RecordUnsupportedFramebufferTextureAttachmentError(const char* functionName, const char* detail) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", functionName, detail));
}
Bool ResolveRepresentableFramebufferTextureUploadTarget(const MG_State::GLState::ITextureObject& textureObject,
TextureUploadTarget& outUploadTarget) {
switch (textureObject.GetTarget()) {
case TextureTarget::Texture1D:
outUploadTarget = TextureUploadTarget::Texture1D;
return true;
case TextureTarget::Texture2D:
outUploadTarget = TextureUploadTarget::Texture2D;
return true;
case TextureTarget::TextureRectangle:
outUploadTarget = TextureUploadTarget::TextureRectangle;
return true;
case TextureTarget::Texture2DMultisample:
outUploadTarget = TextureUploadTarget::Texture2DMultisample;
return true;
default:
outUploadTarget = TextureUploadTarget::Unknown;
return false;
}
}
void AttachFramebufferTextureWithUploadTarget(const char* functionName, GLenum target, GLenum attachment,
GLuint texture, GLint level,
TextureUploadTarget textureUploadTarget) {
if (target == GL_FRAMEBUFFER) {
target = GL_DRAW_FRAMEBUFFER;
}
if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
AttachFramebufferTextureWithUploadTarget(functionName, target, GL_DEPTH_ATTACHMENT, texture, level,
textureUploadTarget);
AttachFramebufferTextureWithUploadTarget(functionName, target, GL_STENCIL_ATTACHMENT, texture, level,
textureUploadTarget);
return;
}
const FramebufferAttachmentType attachmentType = MG_Util::ConvertGLEnumToFramebufferAttachmentType(attachment);
const FramebufferTarget framebufferTarget = MG_Util::ConvertGLEnumToFramebufferTarget(target);
if (!FramebufferImpl::ValidateFramebufferAttachmentType(attachmentType)) return;
if (!FramebufferImpl::ValidateFramebufferTarget(framebufferTarget)) return;
if (!TextureImpl::ValidateTextureName(texture, true)) return;
auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(framebufferTarget);
auto& framebufferObject = bindingSlot.GetBoundObject();
if (!framebufferObject) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", functionName,
"Framebuffer target is bound to no framebuffer object."));
return;
}
if (texture == 0) {
framebufferObject->Detach(attachmentType);
return;
}
auto& textureObject = MG_State::pGLContext->GetTextureObject(texture);
if (!textureObject) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", functionName,
std::format("Texture object {} is not valid.", texture)));
return;
}
const auto expectedTextureTarget = MG_Util::ConvertTextureUploadTargetToTextureTarget(textureUploadTarget);
if (expectedTextureTarget == TextureTarget::Unknown ||
textureObject->GetTarget() != expectedTextureTarget) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>(
"MG_Impl/GLImpl", functionName,
std::format("Attachment target {} does not match texture {} target {}.",
MG_Util::ConvertTextureUploadTargetToString(textureUploadTarget), texture,
MG_Util::ConvertTextureTargetToString(textureObject->GetTarget()))));
return;
}
framebufferObject->AttachTexture(attachmentType, textureObject, textureUploadTarget, level);
}
} // namespace
void BlitFramebuffer_Backend(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, void BlitFramebuffer_Backend(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0,
GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
MG_Backend::gBackendFunctionsTable.GL.BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, MG_Backend::gBackendFunctionsTable.GL.BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
@@ -59,12 +193,53 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
void SampleMaski_State(GLuint maskNumber, GLbitfield mask) { void SampleMaski_State(GLuint maskNumber, GLbitfield mask) {
// TODO: implement if (maskNumber != 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "SampleMaski_State",
"Only sample mask word 0 is currently supported."));
return;
}
MG_State::pGLContext->SetSampleMaskValue(static_cast<Uint32>(mask));
} }
void RenderbufferStorageMultisample_State(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, void RenderbufferStorageMultisample_State(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width,
GLsizei height) { GLsizei height) {
// TODO: implement RenderbufferTarget rbTarget = MG_Util::ConvertGLEnumToRenderbufferTarget(target);
if (!FramebufferImpl::ValidateRenderbufferTarget(rbTarget)) return;
auto& bindingSlot = MG_State::pGLContext->GetRenderbufferBindingSlot(rbTarget);
auto& renderbufferObject = bindingSlot.GetBoundObject();
if (!renderbufferObject) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "RenderbufferStorageMultisample_State",
"Renderbuffer target is bound to no renderbuffer object."));
return;
}
TextureInternalFormat format = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat);
if (!TextureImpl::ValidateTextureInternalFormat(format)) return;
if (samples < 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "RenderbufferStorageMultisample_State",
"Sample count must be non-negative."));
return;
}
if (width < 0 || height < 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "RenderbufferStorageMultisample_State",
"Width and height must be non-negative."));
return;
}
renderbufferObject->AllocateStorage({width, height});
renderbufferObject->SetInternalFormat(format);
renderbufferObject->SetSamples(samples);
} }
void AllocateRenderbufferStorage_State(const SharedPtr<MG_State::GLState::RenderbufferObject>& renderbufferObject, void AllocateRenderbufferStorage_State(const SharedPtr<MG_State::GLState::RenderbufferObject>& renderbufferObject,
@@ -85,6 +260,7 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
renderbufferObject->AllocateStorage({width, height}); renderbufferObject->AllocateStorage({width, height});
renderbufferObject->SetInternalFormat(format); renderbufferObject->SetInternalFormat(format);
renderbufferObject->SetSamples(0);
} }
void RenderbufferStorage_State(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) { void RenderbufferStorage_State(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
@@ -96,11 +272,11 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
GLboolean IsRenderbuffer_State(GLuint renderbuffer) { GLboolean IsRenderbuffer_State(GLuint renderbuffer) {
return MG_State::pGLContext->ValidateRenderbufferName(renderbuffer); return MG_State::pGLContext->ValidateRenderbufferObject(renderbuffer);
} }
GLboolean IsFramebuffer_State(GLuint framebuffer) { GLboolean IsFramebuffer_State(GLuint framebuffer) {
return MG_State::pGLContext->ValidateFramebufferName(framebuffer); return MG_State::pGLContext->ValidateFramebufferObject(framebuffer);
} }
void GetFramebufferAttachmentParameteriv_State(GLenum target, GLenum attachment, GLenum pname, GLint* params) { void GetFramebufferAttachmentParameteriv_State(GLenum target, GLenum attachment, GLenum pname, GLint* params) {
@@ -173,6 +349,26 @@ namespace MobileGL::MG_Impl::GLImpl {
: 0; : 0;
break; break;
case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
if (attachmentObject != nullptr && attachmentObject->IsTexture() && attachmentObject->IsValid()) {
const GLenum glUploadTarget =
MG_Util::ConvertTextureUploadTargetToGLEnum(attachmentObject->GetTextureUploadTarget());
switch (glUploadTarget) {
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
*params = static_cast<GLint>(glUploadTarget);
break;
default:
*params = 0;
break;
}
} else {
*params = 0;
}
break;
case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
*params = 0; *params = 0;
break; break;
@@ -242,6 +438,34 @@ namespace MobileGL::MG_Impl::GLImpl {
"NamedRenderbufferStorage_State"); "NamedRenderbufferStorage_State");
} }
void NamedRenderbufferStorageMultisample_State(GLuint renderbuffer, GLsizei samples, GLenum internalformat,
GLsizei width, GLsizei height) {
auto renderbufferObject =
GetNamedRenderbufferObject_State(renderbuffer, "NamedRenderbufferStorageMultisample_State");
if (!renderbufferObject) return;
TextureInternalFormat format = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat);
if (!TextureImpl::ValidateTextureInternalFormat(format)) return;
if (samples < 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "NamedRenderbufferStorageMultisample_State",
"Sample count must be non-negative."));
return;
}
if (width < 0 || height < 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "NamedRenderbufferStorageMultisample_State",
"Width and height must be non-negative."));
return;
}
renderbufferObject->AllocateStorage({width, height});
renderbufferObject->SetInternalFormat(format);
renderbufferObject->SetSamples(samples);
}
void GenFramebuffers_State(GLsizei n, GLuint* framebuffers) { void GenFramebuffers_State(GLsizei n, GLuint* framebuffers) {
if (n < 0) { if (n < 0) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
@@ -293,12 +517,31 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
void FramebufferTextureLayer_State(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) { void FramebufferTextureLayer_State(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) {
// TODO: implement if (texture == 0) {
const TextureUploadTarget detachTarget = TextureUploadTarget::Texture2D;
AttachFramebufferTextureWithUploadTarget(__func__, target, attachment, texture, level, detachTarget);
return;
}
static_cast<void>(layer);
RecordUnsupportedFramebufferTextureAttachmentError(
__func__,
"Layered framebuffer texture attachments are not represented by the current framebuffer attachment model.");
} }
void FramebufferTexture3D_State(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, void FramebufferTexture3D_State(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level,
GLint zoffset) { GLint zoffset) {
// TODO: implement if (texture == 0) {
TextureUploadTarget textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(textarget);
if (!TextureImpl::ValidateTextureUploadTarget(textureUploadTarget)) return;
AttachFramebufferTextureWithUploadTarget(__func__, target, attachment, texture, level, textureUploadTarget);
return;
}
static_cast<void>(zoffset);
RecordUnsupportedFramebufferTextureAttachmentError(
__func__,
"3D framebuffer texture slice attachments are not represented by the current framebuffer attachment model.");
} }
void FramebufferTexture2D_State(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { void FramebufferTexture2D_State(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {
@@ -318,6 +561,11 @@ namespace MobileGL::MG_Impl::GLImpl {
if (!FramebufferImpl::ValidateFramebufferAttachmentType(attachmentType)) return; if (!FramebufferImpl::ValidateFramebufferAttachmentType(attachmentType)) return;
if (!FramebufferImpl::ValidateFramebufferTarget(framebufferTarget)) return; if (!FramebufferImpl::ValidateFramebufferTarget(framebufferTarget)) return;
if (!TextureImpl::ValidateTextureName(texture, true)) return; if (!TextureImpl::ValidateTextureName(texture, true)) return;
TextureUploadTarget textureUploadTarget = TextureUploadTarget::Unknown;
if (texture != 0) {
textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(textarget);
if (!TextureImpl::ValidateTextureUploadTarget(textureUploadTarget)) return;
}
auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(framebufferTarget); auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(framebufferTarget);
auto& framebufferObject = bindingSlot.GetBoundObject(); auto& framebufferObject = bindingSlot.GetBoundObject();
@@ -343,15 +591,59 @@ namespace MobileGL::MG_Impl::GLImpl {
return; return;
} }
framebufferObject->AttachTexture(attachmentType, textureObject, textureObject ? level : 0); const auto expectedTextureTarget = MG_Util::ConvertTextureUploadTargetToTextureTarget(textureUploadTarget);
if (expectedTextureTarget == TextureTarget::Unknown ||
textureObject->GetTarget() != expectedTextureTarget) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>(
"MG_Impl/GLImpl", "FramebufferTexture2D_State",
std::format("Attachment target {} does not match texture {} target {}.",
MG_Util::ConvertGLEnumToString(textarget),
texture,
MG_Util::ConvertTextureTargetToString(textureObject->GetTarget()))));
return;
}
framebufferObject->AttachTexture(attachmentType, textureObject, textureUploadTarget, textureObject ? level : 0);
} }
void FramebufferTexture1D_State(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { void FramebufferTexture1D_State(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {
// TODO: implement TextureUploadTarget textureUploadTarget = TextureUploadTarget::Unknown;
if (texture != 0) {
textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(textarget);
if (!TextureImpl::ValidateTextureUploadTarget(textureUploadTarget)) return;
} else {
textureUploadTarget = TextureUploadTarget::Texture1D;
}
AttachFramebufferTextureWithUploadTarget(__func__, target, attachment, texture, level, textureUploadTarget);
} }
void FramebufferTexture_State(GLenum target, GLenum attachment, GLuint texture, GLint level) { void FramebufferTexture_State(GLenum target, GLenum attachment, GLuint texture, GLint level) {
FramebufferTexture2D_State(target, attachment, GL_TEXTURE_2D, texture, level); if (texture == 0) {
AttachFramebufferTextureWithUploadTarget(__func__, target, attachment, texture, level,
TextureUploadTarget::Texture2D);
return;
}
auto& textureObject = MG_State::pGLContext->GetTextureObject(texture);
if (!textureObject) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
std::format("Texture object {} is not valid.", texture)));
return;
}
TextureUploadTarget textureUploadTarget = TextureUploadTarget::Unknown;
if (!ResolveRepresentableFramebufferTextureUploadTarget(*textureObject, textureUploadTarget)) {
RecordUnsupportedFramebufferTextureAttachmentError(
__func__,
"Layered or multi-image framebuffer texture targets are not fully represented by the current framebuffer attachment model.");
return;
}
AttachFramebufferTextureWithUploadTarget(__func__, target, attachment, texture, level, textureUploadTarget);
} }
void NamedFramebufferTexture_State(GLuint framebuffer, GLenum attachment, GLuint texture, GLint level) { void NamedFramebufferTexture_State(GLuint framebuffer, GLenum attachment, GLuint texture, GLint level) {
@@ -382,7 +674,15 @@ namespace MobileGL::MG_Impl::GLImpl {
return; return;
} }
framebufferObject->AttachTexture(attachmentType, textureObject, level); TextureUploadTarget textureUploadTarget = TextureUploadTarget::Unknown;
if (!ResolveRepresentableFramebufferTextureUploadTarget(*textureObject, textureUploadTarget)) {
RecordUnsupportedFramebufferTextureAttachmentError(
"NamedFramebufferTexture_State",
"Layered or multi-image framebuffer texture targets are not fully represented by the current framebuffer attachment model.");
return;
}
framebufferObject->AttachTexture(attachmentType, textureObject, textureUploadTarget, level);
} }
void FramebufferRenderbuffer_State(GLenum target, GLenum attachment, GLenum renderbuffertarget, void FramebufferRenderbuffer_State(GLenum target, GLenum attachment, GLenum renderbuffertarget,
@@ -396,7 +696,8 @@ namespace MobileGL::MG_Impl::GLImpl {
RenderbufferTarget rbTarget = MG_Util::ConvertGLEnumToRenderbufferTarget(renderbuffertarget); RenderbufferTarget rbTarget = MG_Util::ConvertGLEnumToRenderbufferTarget(renderbuffertarget);
if (!FramebufferImpl::ValidateFramebufferAttachmentType(attachmentType)) return; if (!FramebufferImpl::ValidateFramebufferAttachmentType(attachmentType)) return;
if (!FramebufferImpl::ValidateFramebufferTarget(framebufferTarget)) return; if (!FramebufferImpl::ValidateFramebufferTarget(framebufferTarget)) return;
if (!FramebufferImpl::ValidateRenderbufferName(renderbuffer)) return; if (!FramebufferImpl::ValidateRenderbufferTarget(rbTarget)) return;
if (!FramebufferImpl::ValidateRenderbufferName(renderbuffer, true)) return;
auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(framebufferTarget); auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(framebufferTarget);
auto& framebufferObject = bindingSlot.GetBoundObject(); auto& framebufferObject = bindingSlot.GetBoundObject();
if (!framebufferObject) { if (!framebufferObject) {
@@ -467,9 +768,9 @@ namespace MobileGL::MG_Impl::GLImpl {
return; return;
} }
if (!fbo) { if (!fbo) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation, MG_State::pGLContext->RecordError(
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, ErrorCode::InvalidOperation,
"Framebuffer object is null.")); MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "Framebuffer object is null."));
return; return;
} }
@@ -489,20 +790,20 @@ namespace MobileGL::MG_Impl::GLImpl {
return; return;
} }
if (isDefaultFBO && attType >= FramebufferAttachmentType::Color0 && if (isDefaultFBO && attType != FramebufferAttachmentType::None &&
attType <= FramebufferAttachmentType::Color31) { (attType < FramebufferAttachmentType::FrontLeft || attType > FramebufferAttachmentType::BackRight)) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>( MakeUnique<GenericErrorInfo>(
"MG_Impl/GLImpl", __func__, "MG_Impl/GLImpl", __func__,
std::format( std::format("FBO is default FBO, but bufs[{}] = {} is not `GL_NONE` or one of the default "
"FBO is default FBO, but bufs[{}] = {} is one of the `GL_COLOR_ATTACHMENTn` tokens.", i, "framebuffer color buffer tokens.",
MG_Util::ConvertGLEnumToString(bufs[i])))); i, MG_Util::ConvertGLEnumToString(bufs[i]))));
return; return;
} }
if (!isDefaultFBO && attType >= FramebufferAttachmentType::FrontLeft && if (!isDefaultFBO && attType != FramebufferAttachmentType::None &&
attType <= FramebufferAttachmentType::BackRight) { (attType < FramebufferAttachmentType::Color0 || attType > FramebufferAttachmentType::Color31)) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>( MakeUnique<GenericErrorInfo>(
@@ -576,6 +877,43 @@ namespace MobileGL::MG_Impl::GLImpl {
// Get bound framebuffer // Get bound framebuffer
auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Read); auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Read);
auto& fbo = bindingSlot.GetBoundObject(); auto& fbo = bindingSlot.GetBoundObject();
if (!fbo) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "No framebuffer bound to read target."));
return;
}
const Bool isDefaultFBO = (fbo == FramebufferImpl::pDefaultFramebufferInfo->defaultFBO);
if (isDefaultFBO && attType != FramebufferAttachmentType::None &&
(attType < FramebufferAttachmentType::FrontLeft || attType > FramebufferAttachmentType::BackRight)) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>(
"MG_Impl/GLImpl", __func__,
std::format("Default framebuffer read buffer {} is not valid.", MG_Util::ConvertGLEnumToString(mode))));
return;
}
if (!isDefaultFBO && attType != FramebufferAttachmentType::None &&
(attType < FramebufferAttachmentType::Color0 || attType > FramebufferAttachmentType::Color31)) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
std::format("Framebuffer object read buffer {} is not valid.",
MG_Util::ConvertGLEnumToString(mode))));
return;
}
if (!isDefaultFBO &&
static_cast<SizeT>(attType) >
static_cast<SizeT>(FramebufferAttachmentType::Color0) +
MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
std::format("Read buffer {} indicates a color buffer that does not exist "
"in the current GL context.",
MG_Util::ConvertGLEnumToString(mode))));
return;
}
fbo->SetReadBuffer(attType); fbo->SetReadBuffer(attType);
} }
@@ -749,10 +1087,16 @@ namespace MobileGL::MG_Impl::GLImpl {
// TODO: distinguish GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT and GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT // TODO: distinguish GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT and GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT
// TODO: GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER, GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER, // TODO: GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER, GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER,
// GL_FRAMEBUFFER_UNSUPPORTED, GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE, // additional GL_FRAMEBUFFER_UNSUPPORTED cases, GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
// GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS // GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS
return framebufferObject->CheckCompleteness() ? GL_FRAMEBUFFER_COMPLETE if (!framebufferObject->CheckCompleteness()) {
: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
}
if (IsActiveBackendDirectVulkan() &&
IsUnsupportedFramebufferForDirectVulkan(*framebufferObject)) {
return GL_FRAMEBUFFER_UNSUPPORTED;
}
return GL_FRAMEBUFFER_COMPLETE;
} }
GLenum CheckNamedFramebufferStatus_State(GLuint framebuffer, GLenum target) { GLenum CheckNamedFramebufferStatus_State(GLuint framebuffer, GLenum target) {
@@ -768,8 +1112,14 @@ namespace MobileGL::MG_Impl::GLImpl {
auto framebufferObject = GetNamedFramebufferObject_State(framebuffer, "CheckNamedFramebufferStatus_State"); auto framebufferObject = GetNamedFramebufferObject_State(framebuffer, "CheckNamedFramebufferStatus_State");
if (!framebufferObject) return GL_FRAMEBUFFER_UNDEFINED; if (!framebufferObject) return GL_FRAMEBUFFER_UNDEFINED;
return framebufferObject->CheckCompleteness() ? GL_FRAMEBUFFER_COMPLETE if (!framebufferObject->CheckCompleteness()) {
: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
}
if (IsActiveBackendDirectVulkan() &&
IsUnsupportedFramebufferForDirectVulkan(*framebufferObject)) {
return GL_FRAMEBUFFER_UNSUPPORTED;
}
return GL_FRAMEBUFFER_COMPLETE;
} }
void GetFramebufferAttachmentParameteriv_Object( void GetFramebufferAttachmentParameteriv_Object(
@@ -866,17 +1216,22 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
void BindRenderbuffer_State(GLenum target, GLuint renderbuffer) { void BindRenderbuffer_State(GLenum target, GLuint renderbuffer) {
if (!FramebufferImpl::ValidateRenderbufferName(renderbuffer)) return; if (!FramebufferImpl::ValidateRenderbufferName(renderbuffer, true)) return;
RenderbufferTarget renderbufferTarget = MG_Util::ConvertGLEnumToRenderbufferTarget(target); RenderbufferTarget renderbufferTarget = MG_Util::ConvertGLEnumToRenderbufferTarget(target);
if (!FramebufferImpl::ValidateRenderbufferTarget(renderbufferTarget)) return; if (!FramebufferImpl::ValidateRenderbufferTarget(renderbufferTarget)) return;
auto& bindingSlot = MG_State::pGLContext->GetRenderbufferBindingSlot(renderbufferTarget);
if (renderbuffer == 0) {
bindingSlot.Bind(nullptr);
return;
}
Bool doesRenderbufferCreated = MG_State::pGLContext->ValidateRenderbufferObject(renderbuffer); Bool doesRenderbufferCreated = MG_State::pGLContext->ValidateRenderbufferObject(renderbuffer);
if (!doesRenderbufferCreated) { if (!doesRenderbufferCreated) {
MG_State::pGLContext->CreateRenderbufferObject(renderbuffer); MG_State::pGLContext->CreateRenderbufferObject(renderbuffer);
} }
auto& renderbufferObject = MG_State::pGLContext->GetRenderbufferObject(renderbuffer); auto& renderbufferObject = MG_State::pGLContext->GetRenderbufferObject(renderbuffer);
auto& bindingSlot = MG_State::pGLContext->GetRenderbufferBindingSlot(renderbufferTarget);
bindingSlot.Bind(renderbufferObject); bindingSlot.Bind(renderbufferObject);
} }
@@ -985,7 +1340,7 @@ namespace MobileGL::MG_Impl::GLImpl {
MG_Backend::gBackendFunctionsTable.GL.ClearBufferiv(buffer, drawbuffer, value); MG_Backend::gBackendFunctionsTable.GL.ClearBufferiv(buffer, drawbuffer, value);
} }
void ReadPixels_State(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) { Bool ReadPixels_State(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) {
TextureInputFormat textureInputFormat = MG_Util::ConvertGLEnumToTextureInputFormat(format); TextureInputFormat textureInputFormat = MG_Util::ConvertGLEnumToTextureInputFormat(format);
TexturePixelDataType texturePixelDataType = MG_Util::ConvertGLEnumToTexturePixelDataType(type); TexturePixelDataType texturePixelDataType = MG_Util::ConvertGLEnumToTexturePixelDataType(type);
@@ -994,7 +1349,7 @@ namespace MobileGL::MG_Impl::GLImpl {
MG_State::pGLContext->RecordError(ErrorCode::InvalidValue, MG_State::pGLContext->RecordError(ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"Width and height must be non-negative")); "Width and height must be non-negative"));
return; return false;
} }
// Validate format // Validate format
@@ -1002,7 +1357,7 @@ namespace MobileGL::MG_Impl::GLImpl {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", "Invalid format")); MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", "Invalid format"));
return; return false;
} }
// Validate type // Validate type
@@ -1010,7 +1365,7 @@ namespace MobileGL::MG_Impl::GLImpl {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", "Invalid pixel data type")); MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", "Invalid pixel data type"));
return; return false;
} }
// Get bound framebuffer // Get bound framebuffer
@@ -1021,7 +1376,7 @@ namespace MobileGL::MG_Impl::GLImpl {
MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation, MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"No framebuffer bound to read target")); "No framebuffer bound to read target"));
return; return false;
} }
// Check framebuffer completeness // Check framebuffer completeness
@@ -1029,7 +1384,7 @@ namespace MobileGL::MG_Impl::GLImpl {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidFramebufferOperation, ErrorCode::InvalidFramebufferOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", "Framebuffer is incomplete")); MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", "Framebuffer is incomplete"));
return; return false;
} }
// Check for required buffers // Check for required buffers
@@ -1039,7 +1394,7 @@ namespace MobileGL::MG_Impl::GLImpl {
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"No stencil buffer for stencil index format")); "No stencil buffer for stencil index format"));
return; return false;
} }
} else if (textureInputFormat == TextureInputFormat::DepthComponent) { } else if (textureInputFormat == TextureInputFormat::DepthComponent) {
if (!framebufferObject->GetAttachment(FramebufferAttachmentType::Depth).IsValid()) { if (!framebufferObject->GetAttachment(FramebufferAttachmentType::Depth).IsValid()) {
@@ -1047,7 +1402,7 @@ namespace MobileGL::MG_Impl::GLImpl {
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"No depth buffer for depth component format")); "No depth buffer for depth component format"));
return; return false;
} }
} else if (textureInputFormat == TextureInputFormat::DepthStencil) { } else if (textureInputFormat == TextureInputFormat::DepthStencil) {
if (!framebufferObject->GetAttachment(FramebufferAttachmentType::Depth).IsValid() || if (!framebufferObject->GetAttachment(FramebufferAttachmentType::Depth).IsValid() ||
@@ -1056,7 +1411,7 @@ namespace MobileGL::MG_Impl::GLImpl {
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"No depth/stencil buffer for depth-stencil format")); "No depth/stencil buffer for depth-stencil format"));
return; return false;
} }
// Validate type for depth/stencil // Validate type for depth/stencil
@@ -1065,7 +1420,7 @@ namespace MobileGL::MG_Impl::GLImpl {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", ErrorCode::InvalidEnum, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"Invalid type for depth-stencil format")); "Invalid type for depth-stencil format"));
return; return false;
} }
} }
@@ -1080,7 +1435,7 @@ namespace MobileGL::MG_Impl::GLImpl {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", ErrorCode::InvalidOperation, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"Pixel pack buffer is currently mapped")); "Pixel pack buffer is currently mapped"));
return; return false;
} }
// Check alignment // Check alignment
@@ -1090,7 +1445,7 @@ namespace MobileGL::MG_Impl::GLImpl {
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"Pixel data not aligned for pixel pack buffer")); "Pixel data not aligned for pixel pack buffer"));
return; return false;
} }
} }
@@ -1102,9 +1457,11 @@ namespace MobileGL::MG_Impl::GLImpl {
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"ReadPixels not supported for multisampled framebuffers")); "ReadPixels not supported for multisampled framebuffers"));
return; return false;
} }
} }
return true;
} }
void ReadPixels_Backend(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) { void ReadPixels_Backend(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) {
@@ -1113,7 +1470,7 @@ namespace MobileGL::MG_Impl::GLImpl {
/* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */ /* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */
void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) { void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) {
ReadPixels_State(x, y, width, height, format, type, pixels); if (!ReadPixels_State(x, y, width, height, format, type, pixels)) return;
ReadPixels_Backend(x, y, width, height, format, type, pixels); ReadPixels_Backend(x, y, width, height, format, type, pixels);
} }
@@ -1170,6 +1527,11 @@ namespace MobileGL::MG_Impl::GLImpl {
NamedRenderbufferStorage_State(renderbuffer, internalformat, width, height); NamedRenderbufferStorage_State(renderbuffer, internalformat, width, height);
} }
void NamedRenderbufferStorageMultisample(GLuint renderbuffer, GLsizei samples, GLenum internalformat,
GLsizei width, GLsizei height) {
NamedRenderbufferStorageMultisample_State(renderbuffer, samples, internalformat, width, height);
}
void GetNamedRenderbufferParameteriv(GLuint renderbuffer, GLenum pname, GLint* params) { void GetNamedRenderbufferParameteriv(GLuint renderbuffer, GLenum pname, GLint* params) {
GetNamedRenderbufferParameteriv_State(renderbuffer, pname, params); GetNamedRenderbufferParameteriv_State(renderbuffer, pname, params);
} }
@@ -26,6 +26,8 @@ namespace MobileGL::MG_Impl::GLImpl {
void GenRenderbuffers(GLsizei n, GLuint* renderbuffers); void GenRenderbuffers(GLsizei n, GLuint* renderbuffers);
void CreateRenderbuffers(GLsizei n, GLuint* renderbuffers); void CreateRenderbuffers(GLsizei n, GLuint* renderbuffers);
void NamedRenderbufferStorage(GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height); void NamedRenderbufferStorage(GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height);
void NamedRenderbufferStorageMultisample(GLuint renderbuffer, GLsizei samples, GLenum internalformat,
GLsizei width, GLsizei height);
void GetNamedRenderbufferParameteriv(GLuint renderbuffer, GLenum pname, GLint* params); void GetNamedRenderbufferParameteriv(GLuint renderbuffer, GLenum pname, GLint* params);
void FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); void FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
void NamedFramebufferRenderbuffer(GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, void NamedFramebufferRenderbuffer(GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget,
File diff suppressed because it is too large Load Diff
+3 -1
View File
@@ -13,8 +13,10 @@ namespace MobileGL::MG_Impl::GLImpl {
/* @INSERTION_POINT:FUNCTION_DECLARATION@ */ /* @INSERTION_POINT:FUNCTION_DECLARATION@ */
const GLubyte* GetString(GLenum name); const GLubyte* GetString(GLenum name);
const GLubyte* GetStringi(GLenum name, GLuint index); const GLubyte* GetStringi(GLenum name, GLuint index);
void GetBooleanv(GLenum pname, GLboolean* params);
void GetFloatv(GLenum pname, GLfloat* params);
void GetIntegerv(GLenum pname, GLint* params); void GetIntegerv(GLenum pname, GLint* params);
void GetInteger64v(GLenum pname, GLint64* data); void GetInteger64v(GLenum pname, GLint64* params);
void GetIntegeri_v(GLenum target, GLuint index, GLint* data); void GetIntegeri_v(GLenum target, GLuint index, GLint* data);
void GetInteger64i_v(GLenum target, GLuint index, GLint64* data); void GetInteger64i_v(GLenum target, GLuint index, GLint64* data);
GLenum GetError(); GLenum GetError();
+218 -120
View File
@@ -16,6 +16,10 @@
#include <MG_Backend/BackendObjects.h> #include <MG_Backend/BackendObjects.h>
namespace MobileGL::MG_Impl::GLImpl { namespace MobileGL::MG_Impl::GLImpl {
static GLint BoolToGLInt(bool value) {
return value ? GL_TRUE : GL_FALSE;
}
static bool CheckShaderNameValidity(Uint shader) { static bool CheckShaderNameValidity(Uint shader) {
if (shader == 0 || !MG_State::pGLContext->ValidateShaderName(shader)) { if (shader == 0 || !MG_State::pGLContext->ValidateShaderName(shader)) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
@@ -80,6 +84,16 @@ namespace MobileGL::MG_Impl::GLImpl {
if (length) *length = sz; if (length) *length = sz;
} }
bool RecordInvalidUniformLocationError(const char* functionName, GLint location, const String& targetDescription) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", functionName,
"location " + std::to_string(location) +
" does not correspond to a valid uniform variable location for " +
targetDescription + "."));
return false;
}
void AttachShader_State(GLuint program, GLuint shader) { void AttachShader_State(GLuint program, GLuint shader) {
auto& programObject = TryToGetProgramObject(program); auto& programObject = TryToGetProgramObject(program);
if (!programObject) return; if (!programObject) return;
@@ -188,9 +202,10 @@ namespace MobileGL::MG_Impl::GLImpl {
std::to_string(program) + ".")); std::to_string(program) + "."));
return; return;
} }
if (type != nullptr) *type = programObject->GetAttribType(index); if (size != nullptr) *size = programObject->GetActiveAttribArraySize(index);
if (type != nullptr) *type = programObject->GetActiveAttribType(index);
if (bufSize == 0) return; if (bufSize == 0) return;
auto& attribName = programObject->GetAttribName(index); auto& attribName = programObject->GetActiveAttribName(index);
CopyStr(bufSize, length, name, attribName.c_str(), (GLsizei)attribName.length()); CopyStr(bufSize, length, name, attribName.c_str(), (GLsizei)attribName.length());
} }
@@ -216,13 +231,38 @@ namespace MobileGL::MG_Impl::GLImpl {
std::to_string(program) + ".")); std::to_string(program) + "."));
return; return;
} }
if (size != nullptr) *size = programObject->GetActiveUniformArraySize(index);
if (type != nullptr) *type = programObject->GetUniformType(index); if (type != nullptr) *type = programObject->GetActiveUniformType(index);
if (bufSize == 0) return; if (bufSize == 0) return;
auto& uniformName = programObject->GetUniformName(index); auto& uniformName = programObject->GetActiveUniformName(index);
CopyStr(bufSize, length, name, uniformName.c_str(), (GLsizei)uniformName.length()); CopyStr(bufSize, length, name, uniformName.c_str(), (GLsizei)uniformName.length());
} }
void GetUniformIndices_State(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames,
GLuint* uniformIndices) {
if (uniformCount < 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"uniformCount " + std::to_string(uniformCount) + " is less than 0."));
return;
}
auto& programObject = TryToGetProgramObject(program);
if (!programObject || !programObject->GetLinkStatus()) return;
if (uniformCount == 0 || uniformNames == nullptr || uniformIndices == nullptr) return;
for (GLsizei i = 0; i < uniformCount; ++i) {
const char* uniformName = uniformNames[i];
if (uniformName == nullptr) {
uniformIndices[i] = GL_INVALID_INDEX;
continue;
}
const Int uniformIndex = programObject->GetActiveUniformIndex(uniformName);
uniformIndices[i] = uniformIndex >= 0 ? static_cast<GLuint>(uniformIndex) : GL_INVALID_INDEX;
}
}
void GetAttachedShaders_State(GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders) { void GetAttachedShaders_State(GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders) {
if (maxCount < 0) { if (maxCount < 0) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
@@ -268,7 +308,7 @@ namespace MobileGL::MG_Impl::GLImpl {
break; break;
case GL_INFO_LOG_LENGTH: { case GL_INFO_LOG_LENGTH: {
const auto& log = programObject->GetInfoLog(); const auto& log = programObject->GetInfoLog();
*params = (GLint)log.length(); *params = log.empty() ? 0 : static_cast<GLint>(log.length()) + 1;
MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params); MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params);
break; break;
} }
@@ -287,7 +327,7 @@ namespace MobileGL::MG_Impl::GLImpl {
MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params); MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params);
break; break;
case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
*params = programObject->GetActiveAttributesMaxLength(); *params = programObject->GetActiveAttributesMaxLength() + 1;
MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params); MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params);
break; break;
case GL_ACTIVE_UNIFORMS: case GL_ACTIVE_UNIFORMS:
@@ -295,7 +335,7 @@ namespace MobileGL::MG_Impl::GLImpl {
MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params); MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params);
break; break;
case GL_ACTIVE_UNIFORM_MAX_LENGTH: case GL_ACTIVE_UNIFORM_MAX_LENGTH:
*params = programObject->GetUniformMaxLength(); *params = programObject->GetUniformMaxLength() + 1;
MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params); MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params);
break; break;
case GL_ACTIVE_UNIFORM_BLOCKS: // GL >= 3.1 case GL_ACTIVE_UNIFORM_BLOCKS: // GL >= 3.1
@@ -303,22 +343,21 @@ namespace MobileGL::MG_Impl::GLImpl {
MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params); MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params);
break; break;
case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: // ditto. case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: // ditto.
*params = programObject->GetActiveUniformBlocksMaxNameLength(); *params = programObject->GetActiveUniformBlocksMaxNameLength() + 1;
MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params); MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params);
break; break;
case GL_COMPUTE_WORK_GROUP_SIZE: { // GL >= 4.3 case GL_COMPUTE_WORK_GROUP_SIZE: { // GL >= 4.3
auto getProgramiv = MG_Backend::gBackendFunctionsTable.GL.GetProgramiv; if (!programObject->GetLinkStatus()) {
if (!getProgramiv) {
params[0] = 1;
params[1] = 1;
params[2] = 1;
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"Backend does not support program integer queries.")); std::to_string(program) +
" is not a program object that has been linked."));
return; return;
} }
getProgramiv(program, pname, params); params[0] = static_cast<GLint>(programObject->GetComputeLocalSize(0));
params[1] = static_cast<GLint>(programObject->GetComputeLocalSize(1));
params[2] = static_cast<GLint>(programObject->GetComputeLocalSize(2));
MGLOG_D("%s: %s = (%d, %d, %d)", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), params[0], MGLOG_D("%s: %s = (%d, %d, %d)", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), params[0],
params[1], params[2]); params[1], params[2]);
break; break;
@@ -423,25 +462,13 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
// Check if location is valid // Check if location is valid
if (location < 0 || location > programObject->GetMaxUniformLocation()) { if (!programObject->IsValidUniformLocation(location)) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, MakeUnique<GenericErrorInfo>(
"MG_Impl/GLImpl", __func__,
"location " + std::to_string(location) + "location " + std::to_string(location) +
" does not correspond to a valid uniform variable location " " does not correspond to a valid uniform variable location for the specified program object."));
"for the specified program object."));
return;
}
// Check if the location corresponds to an active uniform
const auto& uniformName = programObject->GetUniformName(location);
if (uniformName.empty()) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"location " + std::to_string(location) +
" does not correspond to a valid uniform variable location "
"for the specified program object."));
return; return;
} }
@@ -468,12 +495,64 @@ namespace MobileGL::MG_Impl::GLImpl {
// TODO: handle 1i variant as texture unit // TODO: handle 1i variant as texture unit
} }
template <typename T>
void GetUniformScalar_State(GLuint program, GLint location, T* params) {
auto& programObject = TryToGetProgramObject(program);
if (!programObject) return;
if (!programObject->GetLinkStatus()) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
std::to_string(program) + " has not been successfully linked."));
return;
}
if (!programObject->IsValidUniformLocation(location)) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>(
"MG_Impl/GLImpl", __func__,
"location " + std::to_string(location) +
" does not correspond to a valid uniform variable location for the specified program object."));
return;
}
if (programObject->IsUniformOpaqueAtLocation(location)) {
const Int unit = std::max(programObject->GetUniformSamplerOrImageUnitIndex(location), 0);
*params = static_cast<T>(unit);
return;
}
auto offset = programObject->GetUniformOffset(location);
auto size = programObject->GetUniformSizesInBytes(location);
char* pUBO = static_cast<char*>(programObject->MapUBO());
auto* ttype = programObject->GetUniformTType(location);
if constexpr (std::is_same_v<T, GLfloat>) {
if (ttype->isMatrix() && ttype->getMatrixCols() == 3) {
auto* pBase = pUBO + offset;
for (int i = 0; i < ttype->getMatrixRows(); i++) {
Memcpy(reinterpret_cast<char*>(params) + ttype->getMatrixCols() * sizeof(GLfloat) * i,
pBase + 4 * sizeof(GLfloat) * i, ttype->getMatrixCols() * sizeof(GLfloat));
}
return;
}
}
Memcpy(params, pUBO + offset, size);
}
void GetUniformfv_State(GLuint program, GLint location, GLfloat* params) { void GetUniformfv_State(GLuint program, GLint location, GLfloat* params) {
GetUniform_State(program, location, params); GetUniformScalar_State(program, location, params);
} }
void GetUniformiv_State(GLuint program, GLint location, GLint* params) { void GetUniformiv_State(GLuint program, GLint location, GLint* params) {
GetUniform_State(program, location, params); GetUniformScalar_State(program, location, params);
}
void GetUniformuiv_State(GLuint program, GLint location, GLuint* params) {
GetUniformScalar_State(program, location, params);
} }
GLboolean IsProgram_State(GLuint program) { GLboolean IsProgram_State(GLuint program) {
@@ -585,18 +664,11 @@ namespace MobileGL::MG_Impl::GLImpl {
return; return;
} }
if (location > programObject->GetMaxUniformLocation() || location < -1) { for (GLint offset = 0; offset < count; offset++) {
MG_State::pGLContext->RecordError( if (!programObject->IsValidUniformLocation(location + offset)) {
ErrorCode::InvalidOperation, RecordInvalidUniformLocationError(__func__, location + offset, "the current program object");
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"location " + std::to_string(location) +
" is an invalid uniform location for the current program "
"object and location " +
std::to_string(location) + " is not equal to -1."));
return; return;
} }
for (GLint offset = 0; offset < count; offset++) {
Uniform_State<ItemCount>(*programObject, location + offset, value + offset * ItemCount); Uniform_State<ItemCount>(*programObject, location + offset, value + offset * ItemCount);
} }
} }
@@ -616,17 +688,12 @@ namespace MobileGL::MG_Impl::GLImpl {
return; return;
} }
if (location > programObject->GetMaxUniformLocation() || location < -1) { for (GLint offset = 0; offset < count; offset++) {
MG_State::pGLContext->RecordError( if (!programObject->IsValidUniformLocation(location + offset)) {
ErrorCode::InvalidOperation, RecordInvalidUniformLocationError(__func__, location + offset,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "program " + std::to_string(program));
"location " + std::to_string(location) +
" is an invalid uniform location for program " +
std::to_string(program) + "."));
return; return;
} }
for (GLint offset = 0; offset < count; offset++) {
Uniform_State<ItemCount>(*programObject, location + offset, value + offset * ItemCount); Uniform_State<ItemCount>(*programObject, location + offset, value + offset * ItemCount);
} }
} }
@@ -748,19 +815,12 @@ namespace MobileGL::MG_Impl::GLImpl {
return; return;
} }
if (location > programObject->GetMaxUniformLocation() || location < -1) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"location " + std::to_string(location) +
" is an invalid uniform location for the current program "
"object and location " +
std::to_string(location) + " is not equal to -1."));
return;
}
// For matrix uniforms, we handle each matrix individually // For matrix uniforms, we handle each matrix individually
for (GLint i = 0; i < count; i++) { for (GLint i = 0; i < count; i++) {
if (!programObject->IsValidUniformLocation(location + i)) {
RecordInvalidUniformLocationError(__func__, location + i, "the current program object");
return;
}
if (transpose == GL_TRUE) { if (transpose == GL_TRUE) {
// Transpose the matrix before uploading // Transpose the matrix before uploading
GLfloat transposedMatrix[4]; GLfloat transposedMatrix[4];
@@ -786,20 +846,13 @@ namespace MobileGL::MG_Impl::GLImpl {
return; return;
} }
if (location > programObject->GetMaxUniformLocation() || location < -1) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"location " + std::to_string(location) +
" is an invalid uniform location for the current program "
"object and location " +
std::to_string(location) + " is not equal to -1."));
return;
}
// For matrix uniforms, we handle each matrix individually // For matrix uniforms, we handle each matrix individually
// Handle padding in mat3 correctly!! // Handle padding in mat3 correctly!!
for (GLint i = 0; i < count; i++) { for (GLint i = 0; i < count; i++) {
if (!programObject->IsValidUniformLocation(location + i)) {
RecordInvalidUniformLocationError(__func__, location + i, "the current program object");
return;
}
if (transpose == GL_TRUE) { if (transpose == GL_TRUE) {
// Transpose the matrix before uploading // Transpose the matrix before uploading
GLfloat transposedMatrix[9]; GLfloat transposedMatrix[9];
@@ -829,19 +882,12 @@ namespace MobileGL::MG_Impl::GLImpl {
return; return;
} }
if (location > programObject->GetMaxUniformLocation() || location < -1) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"location " + std::to_string(location) +
" is an invalid uniform location for the current program "
"object and location " +
std::to_string(location) + " is not equal to -1."));
return;
}
// For matrix uniforms, we handle each matrix individually // For matrix uniforms, we handle each matrix individually
for (GLint i = 0; i < count; i++) { for (GLint i = 0; i < count; i++) {
if (!programObject->IsValidUniformLocation(location + i)) {
RecordInvalidUniformLocationError(__func__, location + i, "the current program object");
return;
}
if (transpose == GL_TRUE) { if (transpose == GL_TRUE) {
// Transpose the matrix before uploading // Transpose the matrix before uploading
GLfloat transposedMatrix[16]; GLfloat transposedMatrix[16];
@@ -869,17 +915,11 @@ namespace MobileGL::MG_Impl::GLImpl {
return; return;
} }
if (location > programObject->GetMaxUniformLocation() || location < -1) { for (GLint i = 0; i < count; i++) {
MG_State::pGLContext->RecordError( if (!programObject->IsValidUniformLocation(location + i)) {
ErrorCode::InvalidOperation, RecordInvalidUniformLocationError(__func__, location + i, "program " + std::to_string(program));
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"location " + std::to_string(location) +
" is an invalid uniform location for program " +
std::to_string(program) + "."));
return; return;
} }
for (GLint i = 0; i < count; i++) {
if (transpose == GL_TRUE) { if (transpose == GL_TRUE) {
GLfloat transposedMatrix[4]; GLfloat transposedMatrix[4];
TransposeMatrix2x2(value + i * 4, transposedMatrix); TransposeMatrix2x2(value + i * 4, transposedMatrix);
@@ -905,17 +945,11 @@ namespace MobileGL::MG_Impl::GLImpl {
return; return;
} }
if (location > programObject->GetMaxUniformLocation() || location < -1) { for (GLint i = 0; i < count; i++) {
MG_State::pGLContext->RecordError( if (!programObject->IsValidUniformLocation(location + i)) {
ErrorCode::InvalidOperation, RecordInvalidUniformLocationError(__func__, location + i, "program " + std::to_string(program));
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"location " + std::to_string(location) +
" is an invalid uniform location for program " +
std::to_string(program) + "."));
return; return;
} }
for (GLint i = 0; i < count; i++) {
if (transpose == GL_TRUE) { if (transpose == GL_TRUE) {
GLfloat transposedMatrix[9]; GLfloat transposedMatrix[9];
TransposeMatrix3x3(value + i * 9, transposedMatrix); TransposeMatrix3x3(value + i * 9, transposedMatrix);
@@ -945,17 +979,11 @@ namespace MobileGL::MG_Impl::GLImpl {
return; return;
} }
if (location > programObject->GetMaxUniformLocation() || location < -1) { for (GLint i = 0; i < count; i++) {
MG_State::pGLContext->RecordError( if (!programObject->IsValidUniformLocation(location + i)) {
ErrorCode::InvalidOperation, RecordInvalidUniformLocationError(__func__, location + i, "program " + std::to_string(program));
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"location " + std::to_string(location) +
" is an invalid uniform location for program " +
std::to_string(program) + "."));
return; return;
} }
for (GLint i = 0; i < count; i++) {
if (transpose == GL_TRUE) { if (transpose == GL_TRUE) {
GLfloat transposedMatrix[16]; GLfloat transposedMatrix[16];
TransposeMatrix4x4(value + i * 16, transposedMatrix); TransposeMatrix4x4(value + i * 16, transposedMatrix);
@@ -1037,22 +1065,52 @@ namespace MobileGL::MG_Impl::GLImpl {
break; break;
} }
case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: { case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: {
// TODO: deduct global ubo? *params = programObject->GetUniformBlockActiveUniformCount(uniformBlockIndex);
*params = programObject->GetActiveUniformBlocksCount();
MGLOG_D("%s: GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS = %d", __func__, *params); MGLOG_D("%s: GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS = %d", __func__, *params);
break; break;
} }
case GL_UNIFORM_BLOCK_BINDING: { case GL_UNIFORM_BLOCK_BINDING: {
// TODO *params = static_cast<GLint>(programObject->GetUniformBlockBinding(uniformBlockIndex));
MGLOG_D("%s: GL_UNIFORM_BLOCK_BINDING = <TODO>", __func__, *params); MGLOG_D("%s: GL_UNIFORM_BLOCK_BINDING = %d", __func__, *params);
break;
} }
case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
*params = BoolToGLInt(programObject->IsUniformBlockReferencedByStage(uniformBlockIndex, EShLangVertex));
MGLOG_D("%s: GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER = %d", __func__, *params);
break;
case GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER: case GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER:
*params =
BoolToGLInt(programObject->IsUniformBlockReferencedByStage(uniformBlockIndex, EShLangTessControl));
MGLOG_D("%s: GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER = %d", __func__, *params);
break;
case GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER: case GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER:
*params =
BoolToGLInt(programObject->IsUniformBlockReferencedByStage(uniformBlockIndex, EShLangTessEvaluation));
MGLOG_D("%s: GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER = %d", __func__, *params);
break;
case GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER: case GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER:
*params = BoolToGLInt(programObject->IsUniformBlockReferencedByStage(uniformBlockIndex, EShLangGeometry));
MGLOG_D("%s: GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER = %d", __func__, *params);
break;
case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
*params = BoolToGLInt(programObject->IsUniformBlockReferencedByStage(uniformBlockIndex, EShLangFragment));
MGLOG_D("%s: GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER = %d", __func__, *params);
break;
case GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER: case GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER:
*params = BoolToGLInt(programObject->IsUniformBlockReferencedByStage(uniformBlockIndex, EShLangCompute));
MGLOG_D("%s: GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER = %d", __func__, *params);
break;
case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: {
GLint uniformIndexCount = 0;
for (Uint uniformIndex = 0; uniformIndex < programObject->GetUniformCount(); ++uniformIndex) {
if (programObject->GetActiveUniformBlockIndex(uniformIndex) != static_cast<Int>(uniformBlockIndex)) {
continue;
}
params[uniformIndexCount++] = static_cast<GLint>(uniformIndex);
}
MGLOG_D("%s: GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES count = %d", __func__, uniformIndexCount);
break;
}
default: default:
MGLOG_E("%s: unknown pname = %p %s", __func__, pname, MG_Util::ConvertGLEnumToString(pname).c_str()); MGLOG_E("%s: unknown pname = %p %s", __func__, pname, MG_Util::ConvertGLEnumToString(pname).c_str());
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
@@ -1088,7 +1146,7 @@ namespace MobileGL::MG_Impl::GLImpl {
const auto& name = programObject->GetUniformBlockName(uniformBlockIndex); const auto& name = programObject->GetUniformBlockName(uniformBlockIndex);
CopyStr(bufSize, length, uniformBlockName, name.c_str(), (GLsizei)name.length()); CopyStr(bufSize, length, uniformBlockName, name.c_str(), (GLsizei)name.length());
MGLOG_D("%s: \"%s\" at uniformBlockIndex %02d, length = %d", __func__, uniformBlockName, uniformBlockIndex, MGLOG_D("%s: \"%s\" at uniformBlockIndex %02d, length = %d", __func__, uniformBlockName, uniformBlockIndex,
*length); length ? *length : 0);
} }
void BindFragDataLocation_State(GLuint program, GLuint colorNumber, const char* name) { void BindFragDataLocation_State(GLuint program, GLuint colorNumber, const char* name) {
@@ -1170,6 +1228,16 @@ namespace MobileGL::MG_Impl::GLImpl {
GetActiveUniform_State(program, index, bufSize, length, size, type, name); GetActiveUniform_State(program, index, bufSize, length, size, type, name);
} }
void GetActiveUniformName(GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei* length,
GLchar* uniformName) {
GetActiveUniform_State(program, uniformIndex, bufSize, length, nullptr, nullptr, uniformName);
}
void GetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames,
GLuint* uniformIndices) {
GetUniformIndices_State(program, uniformCount, uniformNames, uniformIndices);
}
void GetAttachedShaders(GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders) { void GetAttachedShaders(GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders) {
GetAttachedShaders_State(program, maxCount, count, shaders); GetAttachedShaders_State(program, maxCount, count, shaders);
} }
@@ -1210,6 +1278,10 @@ namespace MobileGL::MG_Impl::GLImpl {
GetUniformiv_State(program, location, params); GetUniformiv_State(program, location, params);
} }
void GetUniformuiv(GLuint program, GLint location, GLuint* params) {
GetUniformuiv_State(program, location, params);
}
GLboolean IsProgram(GLuint program) { GLboolean IsProgram(GLuint program) {
return IsProgram_State(program); return IsProgram_State(program);
} }
@@ -1271,6 +1343,20 @@ namespace MobileGL::MG_Impl::GLImpl {
Uniform1uiv(location, 1, &v0); Uniform1uiv(location, 1, &v0);
} }
void Uniform2ui(GLint location, GLuint v0, GLuint v1) {
GLuint v[] = {v0, v1};
Uniform2uiv(location, 1, v);
}
void Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2) {
GLuint v[] = {v0, v1, v2};
Uniform3uiv(location, 1, v);
}
void Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) {
GLuint v[] = {v0, v1, v2, v3};
Uniform4uiv(location, 1, v);
}
void Uniform1fv(GLint location, GLsizei count, const GLfloat* value) { void Uniform1fv(GLint location, GLsizei count, const GLfloat* value) {
Uniform1fv_State(location, count, value); Uniform1fv_State(location, count, value);
} }
@@ -1304,7 +1390,19 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
void Uniform1uiv(GLint location, GLsizei count, const GLuint* value) { void Uniform1uiv(GLint location, GLsizei count, const GLuint* value) {
Uniform1uiv_State(location, count, value); Uniformv_State<1>(location, count, value);
}
void Uniform2uiv(GLint location, GLsizei count, const GLuint* value) {
Uniformv_State<2>(location, count, value);
}
void Uniform3uiv(GLint location, GLsizei count, const GLuint* value) {
Uniformv_State<3>(location, count, value);
}
void Uniform4uiv(GLint location, GLsizei count, const GLuint* value) {
Uniformv_State<4>(location, count, value);
} }
void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
@@ -22,6 +22,10 @@ namespace MobileGL::MG_Impl::GLImpl {
GLchar* name); GLchar* name);
void GetActiveUniform(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLint* size, GLenum* type, void GetActiveUniform(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLint* size, GLenum* type,
GLchar* name); GLchar* name);
void GetActiveUniformName(GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei* length,
GLchar* uniformName);
void GetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames,
GLuint* uniformIndices);
void GetAttachedShaders(GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders); void GetAttachedShaders(GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders);
GLint GetAttribLocation(GLuint program, const GLchar* name); GLint GetAttribLocation(GLuint program, const GLchar* name);
void GetProgramiv(GLuint program, GLenum pname, GLint* params); void GetProgramiv(GLuint program, GLenum pname, GLint* params);
@@ -32,6 +36,7 @@ namespace MobileGL::MG_Impl::GLImpl {
GLint GetUniformLocation(GLuint program, const GLchar* name); GLint GetUniformLocation(GLuint program, const GLchar* name);
void GetUniformfv(GLuint program, GLint location, GLfloat* params); void GetUniformfv(GLuint program, GLint location, GLfloat* params);
void GetUniformiv(GLuint program, GLint location, GLint* params); void GetUniformiv(GLuint program, GLint location, GLint* params);
void GetUniformuiv(GLuint program, GLint location, GLuint* params);
GLboolean IsProgram(GLuint program); GLboolean IsProgram(GLuint program);
GLboolean IsShader(GLuint shader); GLboolean IsShader(GLuint shader);
void LinkProgram(GLuint program); void LinkProgram(GLuint program);
@@ -46,6 +51,9 @@ namespace MobileGL::MG_Impl::GLImpl {
void Uniform3i(GLint location, GLint v0, GLint v1, GLint v2); void Uniform3i(GLint location, GLint v0, GLint v1, GLint v2);
void Uniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3); void Uniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
void Uniform1ui(GLint location, GLuint v0); void Uniform1ui(GLint location, GLuint v0);
void Uniform2ui(GLint location, GLuint v0, GLuint v1);
void Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2);
void Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
void Uniform1fv(GLint location, GLsizei count, const GLfloat* value); void Uniform1fv(GLint location, GLsizei count, const GLfloat* value);
void Uniform2fv(GLint location, GLsizei count, const GLfloat* value); void Uniform2fv(GLint location, GLsizei count, const GLfloat* value);
void Uniform3fv(GLint location, GLsizei count, const GLfloat* value); void Uniform3fv(GLint location, GLsizei count, const GLfloat* value);
@@ -55,6 +63,9 @@ namespace MobileGL::MG_Impl::GLImpl {
void Uniform3iv(GLint location, GLsizei count, const GLint* value); void Uniform3iv(GLint location, GLsizei count, const GLint* value);
void Uniform4iv(GLint location, GLsizei count, const GLint* value); void Uniform4iv(GLint location, GLsizei count, const GLint* value);
void Uniform1uiv(GLint location, GLsizei count, const GLuint* value); void Uniform1uiv(GLint location, GLsizei count, const GLuint* value);
void Uniform2uiv(GLint location, GLsizei count, const GLuint* value);
void Uniform3uiv(GLint location, GLsizei count, const GLuint* value);
void Uniform4uiv(GLint location, GLsizei count, const GLuint* value);
void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
@@ -14,6 +14,32 @@
#include <MG_Util/Converters/MGToStr/RenderStateEnumConverter.h> #include <MG_Util/Converters/MGToStr/RenderStateEnumConverter.h>
namespace MobileGL::MG_Impl::GLImpl { namespace MobileGL::MG_Impl::GLImpl {
static Float ClampUnitFloat(GLfloat value) {
return std::clamp(static_cast<Float>(value), 0.0f, 1.0f);
}
static Bool ValidateIndexedBlendCapability(GLenum target, GLuint index, const char* functionName) {
if (target != GL_BLEND) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", functionName,
"Only GL_BLEND is supported for indexed capability state."));
return false;
}
if (index >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>(
"MG_Impl/GLImpl", functionName,
"Buffer index " + std::to_string(index) + " is out of range. Max supported is " +
std::to_string(MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS - 1) + "."));
return false;
}
return true;
}
static Bool TryConvertBlendEquation(GLenum mode, const char* functionName, static Bool TryConvertBlendEquation(GLenum mode, const char* functionName,
::MobileGL::BlendEquation& outEquation) { ::MobileGL::BlendEquation& outEquation) {
outEquation = MG_Util::ConvertGLEnumToBlendEquation(mode); outEquation = MG_Util::ConvertGLEnumToBlendEquation(mode);
@@ -27,6 +53,43 @@ namespace MobileGL::MG_Impl::GLImpl {
return false; return false;
} }
static Bool TryDecodeStencilFace(GLenum face, const char* functionName, Bool& applyFront, Bool& applyBack) {
switch (face) {
case GL_FRONT:
applyFront = true;
applyBack = false;
return true;
case GL_BACK:
applyFront = false;
applyBack = true;
return true;
case GL_FRONT_AND_BACK:
applyFront = true;
applyBack = true;
return true;
default:
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", functionName,
"Stencil face enum " + MG_Util::ConvertGLEnumToString(face) +
" is not supported."));
return false;
}
}
static Bool TryConvertStencilOperation(GLenum value, const char* functionName, const char* paramName,
StencilOperation& outOperation) {
outOperation = MG_Util::ConvertGLEnumToStencilOperation(value);
if (outOperation != StencilOperation::Unknown) return true;
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", functionName,
String(paramName) + " enum " + MG_Util::ConvertGLEnumToString(value) +
" is not supported."));
return false;
}
void Viewport_State(GLint x, GLint y, GLsizei width, GLsizei height) { void Viewport_State(GLint x, GLint y, GLsizei width, GLsizei height) {
if (width < 0 || height < 0) { if (width < 0 || height < 0) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidValue, MG_State::pGLContext->RecordError(ErrorCode::InvalidValue,
@@ -39,27 +102,74 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
void StencilOpSeparate_State(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass) { void StencilOpSeparate_State(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass) {
// TODO: implement Bool applyFront = false;
Bool applyBack = false;
if (!TryDecodeStencilFace(face, "StencilOpSeparate_State", applyFront, applyBack)) return;
StencilOperation failOp = StencilOperation::Unknown;
StencilOperation depthFailOp = StencilOperation::Unknown;
StencilOperation depthPassOp = StencilOperation::Unknown;
if (!TryConvertStencilOperation(sfail, "StencilOpSeparate_State", "sfail", failOp) ||
!TryConvertStencilOperation(dpfail, "StencilOpSeparate_State", "dpfail", depthFailOp) ||
!TryConvertStencilOperation(dppass, "StencilOpSeparate_State", "dppass", depthPassOp)) {
return;
}
if (applyFront) {
MG_State::pGLContext->SetStencilOp(StencilFace::Front, failOp, depthFailOp, depthPassOp);
}
if (applyBack) {
MG_State::pGLContext->SetStencilOp(StencilFace::Back, failOp, depthFailOp, depthPassOp);
}
} }
void StencilOp_State(GLenum fail, GLenum zfail, GLenum zpass) { void StencilOp_State(GLenum fail, GLenum zfail, GLenum zpass) {
// TODO: implement StencilOpSeparate_State(GL_FRONT_AND_BACK, fail, zfail, zpass);
} }
void StencilMaskSeparate_State(GLenum face, GLuint mask) { void StencilMaskSeparate_State(GLenum face, GLuint mask) {
// TODO: implement Bool applyFront = false;
Bool applyBack = false;
if (!TryDecodeStencilFace(face, "StencilMaskSeparate_State", applyFront, applyBack)) return;
if (applyFront) {
MG_State::pGLContext->SetStencilMask(StencilFace::Front, mask);
}
if (applyBack) {
MG_State::pGLContext->SetStencilMask(StencilFace::Back, mask);
}
} }
void StencilMask_State(GLuint mask) { void StencilMask_State(GLuint mask) {
// TODO: implement StencilMaskSeparate_State(GL_FRONT_AND_BACK, mask);
} }
void StencilFuncSeparate_State(GLenum face, GLenum func, GLint ref, GLuint mask) { void StencilFuncSeparate_State(GLenum face, GLenum func, GLint ref, GLuint mask) {
// TODO: implement Bool applyFront = false;
Bool applyBack = false;
if (!TryDecodeStencilFace(face, "StencilFuncSeparate_State", applyFront, applyBack)) return;
DepthTestFunc depthFunc = MG_Util::ConvertGLEnumToDepthTestFunc(func);
if (depthFunc == DepthTestFunc::Unknown) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "StencilFuncSeparate_State",
"Stencil func enum " + MG_Util::ConvertGLEnumToString(func) +
" is not supported."));
return;
}
const Int clampedRef = std::max(ref, 0);
if (applyFront) {
MG_State::pGLContext->SetStencilFunc(StencilFace::Front, depthFunc, clampedRef, mask);
}
if (applyBack) {
MG_State::pGLContext->SetStencilFunc(StencilFace::Back, depthFunc, clampedRef, mask);
}
} }
void StencilFunc_State(GLenum func, GLint ref, GLuint mask) { void StencilFunc_State(GLenum func, GLint ref, GLuint mask) {
// TODO: implement StencilFuncSeparate_State(GL_FRONT_AND_BACK, func, ref, mask);
} }
void Scissor_State(GLint x, GLint y, GLsizei width, GLsizei height) { void Scissor_State(GLint x, GLint y, GLsizei width, GLsizei height) {
@@ -74,11 +184,11 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
void SampleCoverage_State(GLfloat value, GLboolean invert) { void SampleCoverage_State(GLfloat value, GLboolean invert) {
// TODO: implement MG_State::pGLContext->SetSampleCoverage(std::clamp(static_cast<Float>(value), 0.0f, 1.0f), invert == GL_TRUE);
} }
void PolygonOffset_State(GLfloat factor, GLfloat units) { void PolygonOffset_State(GLfloat factor, GLfloat units) {
// TODO: implement MG_State::pGLContext->SetPolygonOffset(static_cast<Float>(factor), static_cast<Float>(units));
} }
void PolygonMode_State(GLenum face, GLenum mode) { void PolygonMode_State(GLenum face, GLenum mode) {
@@ -86,7 +196,15 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
void PointSize_State(GLfloat size) { void PointSize_State(GLfloat size) {
// TODO: implement if (size <= 0.0f) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "PointSize_State",
"Point size must be greater than zero."));
return;
}
MG_State::pGLContext->SetPointSize(static_cast<Float>(size));
} }
void PointParameterf_State(GLenum pname, GLfloat param) { void PointParameterf_State(GLenum pname, GLfloat param) {
@@ -114,14 +232,36 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
void LogicOp_State(GLenum opcode) { void LogicOp_State(GLenum opcode) {
// TODO: implement LogicOperation logicOp = MG_Util::ConvertGLEnumToLogicOperation(opcode);
if (logicOp == LogicOperation::Unknown) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "LogicOp_State",
"Logic op enum " + MG_Util::ConvertGLEnumToString(opcode) +
" is not supported."));
return;
}
MG_State::pGLContext->SetLogicOp(logicOp);
} }
void LineWidth_State(GLfloat width) { void LineWidth_State(GLfloat width) {
// TODO: implement if (width <= 0.0f) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "LineWidth_State",
"Line width must be greater than zero."));
return;
}
MG_State::pGLContext->SetLineWidth(static_cast<Float>(width));
} }
GLboolean IsEnabledi_State(GLenum target, GLuint index) { GLboolean IsEnabledi_State(GLenum target, GLuint index) {
if (!ValidateIndexedBlendCapability(target, index, "IsEnabledi_State")) {
return GL_FALSE;
}
CapabilityInput capInput = MG_Util::ConvertGLEnumToCapabilityInput(target); CapabilityInput capInput = MG_Util::ConvertGLEnumToCapabilityInput(target);
if (capInput == CapabilityInput::Unknown) { if (capInput == CapabilityInput::Unknown) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
@@ -135,6 +275,18 @@ namespace MobileGL::MG_Impl::GLImpl {
return MG_State::pGLContext->IsCapabilityEnabledIndexed(capInput, index) ? GL_TRUE : GL_FALSE; return MG_State::pGLContext->IsCapabilityEnabledIndexed(capInput, index) ? GL_TRUE : GL_FALSE;
} }
void GetBooleani_v_State(GLenum target, GLuint index, GLboolean* data) {
if (!data) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetBooleani_v_State",
"data pointer cannot be null."));
return;
}
*data = IsEnabledi_State(target, index);
}
GLboolean IsEnabled_State(GLenum cap) { GLboolean IsEnabled_State(GLenum cap) {
CapabilityInput capInput = MG_Util::ConvertGLEnumToCapabilityInput(cap); CapabilityInput capInput = MG_Util::ConvertGLEnumToCapabilityInput(cap);
if (capInput == CapabilityInput::Unknown) { if (capInput == CapabilityInput::Unknown) {
@@ -212,7 +364,8 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
void DepthRange_State(GLclampd near_val, GLclampd far_val) { void DepthRange_State(GLclampd near_val, GLclampd far_val) {
// TODO: implement MG_State::pGLContext->SetDepthRange(
FloatVec2(ClampUnitFloat(static_cast<GLfloat>(near_val)), ClampUnitFloat(static_cast<GLfloat>(far_val))));
} }
void DepthMask_State(GLboolean flag) { void DepthMask_State(GLboolean flag) {
@@ -304,7 +457,8 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
void BlendColor_State(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { void BlendColor_State(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
// TODO: implement MG_State::pGLContext->SetBlendColor(
FloatVec4(ClampUnitFloat(red), ClampUnitFloat(green), ClampUnitFloat(blue), ClampUnitFloat(alpha)));
} }
void ClearStencil_State(GLint s) { void ClearStencil_State(GLint s) {
@@ -374,6 +528,10 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
void Disablei_State(GLenum target, GLuint index) { void Disablei_State(GLenum target, GLuint index) {
if (!ValidateIndexedBlendCapability(target, index, "Disablei_State")) {
return;
}
auto capInput = MG_Util::ConvertGLEnumToCapabilityInput(target); auto capInput = MG_Util::ConvertGLEnumToCapabilityInput(target);
if (capInput == CapabilityInput::Unknown) { if (capInput == CapabilityInput::Unknown) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
@@ -388,6 +546,10 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
void Enablei_State(GLenum target, GLuint index) { void Enablei_State(GLenum target, GLuint index) {
if (!ValidateIndexedBlendCapability(target, index, "Enablei_State")) {
return;
}
auto capInput = MG_Util::ConvertGLEnumToCapabilityInput(target); auto capInput = MG_Util::ConvertGLEnumToCapabilityInput(target);
if (capInput == CapabilityInput::Unknown) { if (capInput == CapabilityInput::Unknown) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
@@ -418,6 +580,10 @@ namespace MobileGL::MG_Impl::GLImpl {
BlendFuncSeparatei_State(buf, srcRGB, dstRGB, srcAlpha, dstAlpha); BlendFuncSeparatei_State(buf, srcRGB, dstRGB, srcAlpha, dstAlpha);
} }
void GetBooleani_v(GLenum target, GLuint index, GLboolean* data) {
GetBooleani_v_State(target, index, data);
}
void Disablei(GLenum target, GLuint index) { void Disablei(GLenum target, GLuint index) {
Disablei_State(target, index); Disablei_State(target, index);
} }
@@ -15,6 +15,7 @@ namespace MobileGL::MG_Impl::GLImpl {
void BlendEquationSeparatei(GLuint buf, GLenum modeRGB, GLenum modeAlpha); void BlendEquationSeparatei(GLuint buf, GLenum modeRGB, GLenum modeAlpha);
void BlendFunci(GLuint buf, GLenum src, GLenum dst); void BlendFunci(GLuint buf, GLenum src, GLenum dst);
void BlendFuncSeparatei(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); void BlendFuncSeparatei(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
void GetBooleani_v(GLenum target, GLuint index, GLboolean* data);
void Disablei(GLenum target, GLuint index); void Disablei(GLenum target, GLuint index);
void Enablei(GLenum target, GLuint index); void Enablei(GLenum target, GLuint index);
void BlendFunc(GLenum sfactor, GLenum dfactor); void BlendFunc(GLenum sfactor, GLenum dfactor);
@@ -13,7 +13,31 @@
#include <MG_Util/Converters/MGToGL/TextureEnumConverter.h> #include <MG_Util/Converters/MGToGL/TextureEnumConverter.h>
namespace MobileGL::MG_Impl::GLImpl { namespace MobileGL::MG_Impl::GLImpl {
namespace {
Bool ValidateSamplerParameterValue(GLenum pname, const void* param, Bool isFloat, Bool isInteger) {
if (param == nullptr) return false;
switch (pname) {
case GL_TEXTURE_MIN_LOD:
case GL_TEXTURE_MAX_LOD:
case GL_TEXTURE_LOD_BIAS:
return true;
default:
break;
}
if (isFloat) {
return SamplerImpl::ValidateSamplerFloatParam(pname, *(const GLfloat*)param);
}
if (isInteger) {
return SamplerImpl::ValidateSamplerIntParam(pname, static_cast<GLint>(*(const GLuint*)param));
}
return SamplerImpl::ValidateSamplerIntParam(pname, *(const GLint*)param);
}
} // namespace
void SetSamplerParam_State(GLuint sampler, GLenum pname, const void* param, bool isFloat, bool isInteger) { void SetSamplerParam_State(GLuint sampler, GLenum pname, const void* param, bool isFloat, bool isInteger) {
if (param == nullptr) return;
if (!SamplerImpl::ValidateSamplerName(sampler)) return; if (!SamplerImpl::ValidateSamplerName(sampler)) return;
Bool doesSamplerObjectCreated = MG_State::pGLContext->ValidateSamplerObject(sampler); Bool doesSamplerObjectCreated = MG_State::pGLContext->ValidateSamplerObject(sampler);
@@ -23,6 +47,7 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
auto& samplerObj = MG_State::pGLContext->GetSamplerObject(sampler); auto& samplerObj = MG_State::pGLContext->GetSamplerObject(sampler);
if (!SamplerImpl::ValidateSamplerObject(sampler)) return; if (!SamplerImpl::ValidateSamplerObject(sampler)) return;
if (!ValidateSamplerParameterValue(pname, param, isFloat, isInteger)) return;
using namespace MG_Util; using namespace MG_Util;
switch (pname) { switch (pname) {
@@ -65,6 +90,7 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
void GetSamplerParam_State(GLuint sampler, GLenum pname, void* params, bool isFloat, bool isInteger) { void GetSamplerParam_State(GLuint sampler, GLenum pname, void* params, bool isFloat, bool isInteger) {
if (params == nullptr) return;
if (!SamplerImpl::ValidateSamplerName(sampler)) return; if (!SamplerImpl::ValidateSamplerName(sampler)) return;
Bool doesSamplerObjectCreated = MG_State::pGLContext->ValidateSamplerObject(sampler); Bool doesSamplerObjectCreated = MG_State::pGLContext->ValidateSamplerObject(sampler);
+53 -2
View File
@@ -9,6 +9,9 @@
#include "GL_Sync.h" #include "GL_Sync.h"
#include <MG_State/GLState/Core.h> #include <MG_State/GLState/Core.h>
#include <MG_Backend/BackendObjects.h>
#include <MG_Backend/DirectGLES/BackendObject_DirectGLES.h>
#include <MG_Util/BackendLoaders/OpenGL/Loader.h>
#include <MG_State/GLState/ErrorState/Error.h> #include <MG_State/GLState/ErrorState/Error.h>
namespace MobileGL::MG_Impl::GLImpl { namespace MobileGL::MG_Impl::GLImpl {
@@ -16,6 +19,7 @@ namespace MobileGL::MG_Impl::GLImpl {
struct SyncObject { struct SyncObject {
GLenum Condition = GL_SYNC_GPU_COMMANDS_COMPLETE; GLenum Condition = GL_SYNC_GPU_COMMANDS_COMPLETE;
GLbitfield Flags = 0; GLbitfield Flags = 0;
GLsync BackendHandle = nullptr;
}; };
UnorderedMap<GLsync, UniquePtr<SyncObject>> g_syncObjects; UnorderedMap<GLsync, UniquePtr<SyncObject>> g_syncObjects;
@@ -25,6 +29,15 @@ namespace MobileGL::MG_Impl::GLImpl {
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", funcName, Move(message))); MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", funcName, Move(message)));
} }
const MG_External::GLESFunctionsTable* TryGetDirectGLESFunctions() {
auto* activeBackend = MG_Backend::pActiveBackendObject.get();
if (!activeBackend) return nullptr;
auto* directGLESBackend =
dynamic_cast<MG_Backend::DirectGLES::BackendObject_DirectGLES*>(activeBackend);
return directGLESBackend ? &directGLESBackend->GetGLESFunctions() : nullptr;
}
SyncObject* GetSyncObject(GLsync sync, const char* funcName) { SyncObject* GetSyncObject(GLsync sync, const char* funcName) {
auto it = g_syncObjects.find(sync); auto it = g_syncObjects.find(sync);
if (sync == nullptr || it == g_syncObjects.end()) { if (sync == nullptr || it == g_syncObjects.end()) {
@@ -48,6 +61,12 @@ namespace MobileGL::MG_Impl::GLImpl {
auto syncObject = MakeUnique<SyncObject>(); auto syncObject = MakeUnique<SyncObject>();
syncObject->Condition = condition; syncObject->Condition = condition;
syncObject->Flags = flags; syncObject->Flags = flags;
if (const auto* glesFuncs = TryGetDirectGLESFunctions(); glesFuncs && glesFuncs->glFenceSync) {
syncObject->BackendHandle = glesFuncs->glFenceSync(condition, flags);
if (syncObject->BackendHandle == nullptr) {
return nullptr;
}
}
GLsync handle = reinterpret_cast<GLsync>(syncObject.get()); GLsync handle = reinterpret_cast<GLsync>(syncObject.get());
g_syncObjects[handle] = Move(syncObject); g_syncObjects[handle] = Move(syncObject);
return handle; return handle;
@@ -64,7 +83,15 @@ namespace MobileGL::MG_Impl::GLImpl {
"Flags can only contain GL_SYNC_FLUSH_COMMANDS_BIT."); "Flags can only contain GL_SYNC_FLUSH_COMMANDS_BIT.");
return GL_WAIT_FAILED; return GL_WAIT_FAILED;
} }
if (!GetSyncObject(sync, "ClientWaitSync")) return GL_WAIT_FAILED; auto* syncObject = GetSyncObject(sync, "ClientWaitSync");
if (!syncObject) return GL_WAIT_FAILED;
if (syncObject->BackendHandle != nullptr) {
if (const auto* glesFuncs = TryGetDirectGLESFunctions(); glesFuncs && glesFuncs->glClientWaitSync) {
return glesFuncs->glClientWaitSync(syncObject->BackendHandle, flags, timeout);
}
RecordSyncError("ClientWaitSync", ErrorCode::InvalidOperation, "Backend sync wait is unavailable.");
return GL_WAIT_FAILED;
}
return GL_ALREADY_SIGNALED; return GL_ALREADY_SIGNALED;
} }
@@ -77,7 +104,15 @@ namespace MobileGL::MG_Impl::GLImpl {
RecordSyncError("WaitSync", ErrorCode::InvalidValue, "Timeout must be GL_TIMEOUT_IGNORED."); RecordSyncError("WaitSync", ErrorCode::InvalidValue, "Timeout must be GL_TIMEOUT_IGNORED.");
return; return;
} }
(void)GetSyncObject(sync, "WaitSync"); auto* syncObject = GetSyncObject(sync, "WaitSync");
if (!syncObject) return;
if (syncObject->BackendHandle != nullptr) {
if (const auto* glesFuncs = TryGetDirectGLESFunctions(); glesFuncs && glesFuncs->glWaitSync) {
glesFuncs->glWaitSync(syncObject->BackendHandle, flags, timeout);
return;
}
RecordSyncError("WaitSync", ErrorCode::InvalidOperation, "Backend sync wait is unavailable.");
}
} }
void DeleteSync(GLsync sync) { void DeleteSync(GLsync sync) {
@@ -87,6 +122,11 @@ namespace MobileGL::MG_Impl::GLImpl {
RecordSyncError("DeleteSync", ErrorCode::InvalidValue, "Sync object is not valid."); RecordSyncError("DeleteSync", ErrorCode::InvalidValue, "Sync object is not valid.");
return; return;
} }
if (it->second->BackendHandle != nullptr) {
if (const auto* glesFuncs = TryGetDirectGLESFunctions(); glesFuncs && glesFuncs->glDeleteSync) {
glesFuncs->glDeleteSync(it->second->BackendHandle);
}
}
g_syncObjects.erase(it); g_syncObjects.erase(it);
} }
@@ -95,9 +135,20 @@ namespace MobileGL::MG_Impl::GLImpl {
RecordSyncError("GetSynciv", ErrorCode::InvalidValue, "bufSize must be non-negative."); RecordSyncError("GetSynciv", ErrorCode::InvalidValue, "bufSize must be non-negative.");
return; return;
} }
if (bufSize > 0 && values == nullptr) {
RecordSyncError("GetSynciv", ErrorCode::InvalidValue,
"values must not be null when bufSize is positive.");
return;
}
auto* syncObject = GetSyncObject(sync, "GetSynciv"); auto* syncObject = GetSyncObject(sync, "GetSynciv");
if (!syncObject) return; if (!syncObject) return;
if (syncObject->BackendHandle != nullptr) {
if (const auto* glesFuncs = TryGetDirectGLESFunctions(); glesFuncs && glesFuncs->glGetSynciv) {
glesFuncs->glGetSynciv(syncObject->BackendHandle, pname, bufSize, length, values);
return;
}
}
GLint value = 0; GLint value = 0;
switch (pname) { switch (pname) {
File diff suppressed because it is too large Load Diff
@@ -16,18 +16,45 @@ namespace MobileGL::MG_Impl::GLImpl {
void GenerateMipmap(GLenum target); void GenerateMipmap(GLenum target);
void GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels); void GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels);
void CreateTextures(GLenum target, GLsizei n, GLuint* textures); void CreateTextures(GLenum target, GLsizei n, GLuint* textures);
void TextureStorage1D(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width);
void TextureStorage2D(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); void TextureStorage2D(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
void TextureStorage3D(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height,
GLsizei depth);
void TextureStorage2DMultisample(GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width,
GLsizei height, GLboolean fixedsamplelocations);
void TextureStorage3DMultisample(GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width,
GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
void TextureSubImage1D(GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type,
const void* pixels);
void TextureSubImage2D(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, void TextureSubImage2D(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
GLenum format, GLenum type, const void* pixels); GLenum format, GLenum type, const void* pixels);
void TextureSubImage3D(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width,
GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels);
void TextureParameterf(GLuint texture, GLenum pname, GLfloat param); void TextureParameterf(GLuint texture, GLenum pname, GLfloat param);
void TextureParameterfv(GLuint texture, GLenum pname, const GLfloat* params);
void TextureParameteri(GLuint texture, GLenum pname, GLint param); void TextureParameteri(GLuint texture, GLenum pname, GLint param);
void TextureParameterIiv(GLuint texture, GLenum pname, const GLint* params);
void TextureParameterIuiv(GLuint texture, GLenum pname, const GLuint* params);
void TextureParameteriv(GLuint texture, GLenum pname, const GLint* params); void TextureParameteriv(GLuint texture, GLenum pname, const GLint* params);
void GenerateTextureMipmap(GLuint texture);
void BindTextureUnit(GLuint unit, GLuint texture); void BindTextureUnit(GLuint unit, GLuint texture);
void GetTextureImage(GLuint texture, GLint level, GLenum format, GLenum type, GLsizei bufSize, void* pixels); void GetTextureImage(GLuint texture, GLint level, GLenum format, GLenum type, GLsizei bufSize, void* pixels);
void GetTextureSubImage(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, void GetTextureSubImage(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width,
GLsizei height, GLsizei depth, GLenum format, GLenum type, GLsizei bufSize, void* pixels); GLsizei height, GLsizei depth, GLenum format, GLenum type, GLsizei bufSize, void* pixels);
void GetTextureParameterfv(GLuint texture, GLenum pname, GLfloat* params);
void GetTextureParameterIiv(GLuint texture, GLenum pname, GLint* params);
void GetTextureParameterIuiv(GLuint texture, GLenum pname, GLuint* params);
void GetTextureParameteriv(GLuint texture, GLenum pname, GLint* params); void GetTextureParameteriv(GLuint texture, GLenum pname, GLint* params);
void GetTextureLevelParameterfv(GLuint texture, GLint level, GLenum pname, GLfloat* params);
void GetTextureLevelParameteriv(GLuint texture, GLint level, GLenum pname, GLint* params); void GetTextureLevelParameteriv(GLuint texture, GLint level, GLenum pname, GLint* params);
void TexStorage1D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
void TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
void TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height,
GLsizei depth);
void TexStorage2DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width,
GLsizei height, GLboolean fixedsamplelocations);
void TexStorage3DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width,
GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
void TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, void TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width,
GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels); GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels);
void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
@@ -59,6 +86,8 @@ namespace MobileGL::MG_Impl::GLImpl {
void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params); void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
void GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* params); void GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* params);
void GetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat* params); void GetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat* params);
void GetMultisamplefv(GLenum pname, GLuint index, GLfloat* val);
void GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params);
void GetCompressedTexImage(GLenum target, GLint level, void* img); void GetCompressedTexImage(GLenum target, GLint level, void* img);
void GenTextures(GLsizei n, GLuint* textures); void GenTextures(GLsizei n, GLuint* textures);
void DeleteTextures(GLsizei n, const GLuint* textures); void DeleteTextures(GLsizei n, const GLuint* textures);
@@ -7,7 +7,11 @@
// End of Source File Header // End of Source File Header
#include "ProxyTexture.h" #include "ProxyTexture.h"
#include <MG_State/GLState/TextureState/TextureObject1D.h>
#include <MG_State/GLState/TextureState/TextureObject2D.h> #include <MG_State/GLState/TextureState/TextureObject2D.h>
#include <MG_State/GLState/TextureState/TextureObject2DCube.h>
#include <MG_State/GLState/TextureState/TextureObject3D.h>
#include <MG_State/GLState/TextureState/TextureObjectStubs.h>
namespace MobileGL::MG_Impl::GLImpl::TextureImpl { namespace MobileGL::MG_Impl::GLImpl::TextureImpl {
UniquePtr<ProxyTextureManager> pProxyTextureManager; UniquePtr<ProxyTextureManager> pProxyTextureManager;
@@ -37,7 +41,39 @@ namespace MobileGL::MG_Impl::GLImpl::TextureImpl {
m_proxyTexturesMap.erase(it); m_proxyTexturesMap.erase(it);
} }
auto& obj = m_proxyTexturesMap[target]; auto& obj = m_proxyTexturesMap[target];
switch (target) {
case TextureUploadTarget::ProxyTexture1D:
case TextureUploadTarget::ProxyTexture1DArray:
obj = MakeShared<MG_State::GLState::TextureObject1D>(0);
break;
case TextureUploadTarget::ProxyTexture2D:
obj = MakeShared<MG_State::GLState::TextureObject2D>(0); obj = MakeShared<MG_State::GLState::TextureObject2D>(0);
break;
case TextureUploadTarget::ProxyTexture3D:
obj = MakeShared<MG_State::GLState::TextureObject3D>(0);
break;
case TextureUploadTarget::ProxyCubeMap:
obj = MakeShared<MG_State::GLState::TextureObject2DCube>(0);
break;
case TextureUploadTarget::ProxyTextureRectangle:
obj = MakeShared<MG_State::GLState::TextureObjectRectangle>(0);
break;
case TextureUploadTarget::ProxyTexture2DArray:
obj = MakeShared<MG_State::GLState::TextureObject2DArray>(0);
break;
case TextureUploadTarget::ProxyCubeMapArray:
obj = MakeShared<MG_State::GLState::TextureObjectCubeMapArray>(0);
break;
case TextureUploadTarget::ProxyTexture2DMultisample:
obj = MakeShared<MG_State::GLState::TextureObject2DMultisample>(0);
break;
case TextureUploadTarget::ProxyTexture2DMultisampleArray:
obj = MakeShared<MG_State::GLState::TextureObject2DMultisampleArray>(0);
break;
default:
obj = MakeShared<MG_State::GLState::TextureObject2D>(0);
break;
}
return obj; return obj;
} }
@@ -230,6 +230,18 @@ namespace MobileGL::MG_Impl::GLImpl::TextureImpl {
return false; return false;
} }
} }
if (target == TextureUploadTarget::Texture2DMultisample ||
target == TextureUploadTarget::ProxyTexture2DMultisample ||
target == TextureUploadTarget::Texture2DMultisampleArray ||
target == TextureUploadTarget::ProxyTexture2DMultisampleArray) {
if (level != 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureLevelWithUploadTarget",
"Level must be zero for multisample textures"));
return false;
}
}
return true; return true;
} }
@@ -12,8 +12,64 @@
#include <MG_State/GLState/Core.h> #include <MG_State/GLState/Core.h>
#include <MG_State/GLState/ErrorState/Error.h> #include <MG_State/GLState/ErrorState/Error.h>
#include <MG_Util/Converters/GLToMG/DataTypeConverter.h> #include <MG_Util/Converters/GLToMG/DataTypeConverter.h>
#include <MG_Util/Converters/MGToGL/DataTypeConverter.h>
namespace MobileGL::MG_Impl::GLImpl { namespace MobileGL::MG_Impl::GLImpl {
namespace {
static bool ValidateCurrentVertexAttribIndex(GLuint index, const char* funcName) {
if (!VertexArrayImpl::ValidateVertexAttributeIndex(index)) return false;
if (index == 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", funcName,
"Generic vertex attribute 0 current value cannot be modified."));
return false;
}
return true;
}
static bool TryGetVertexAttribute(GLuint index, const MG_State::GLState::VertexAttribute** outAttr) {
if (!VertexArrayImpl::ValidateVertexAttributeIndex(index)) return false;
auto& vao = MG_State::pGLContext->GetBoundVertexArray();
if (!vao) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "No vertex array object is bound."));
return false;
}
*outAttr = &vao->GetAttribute(index);
return true;
}
static bool IsCurrentVertexAttribQuery(GLenum pname) {
return pname == GL_CURRENT_VERTEX_ATTRIB;
}
static bool ValidateVertexAttribPname(GLenum pname) {
switch (pname) {
case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
case GL_VERTEX_ATTRIB_ARRAY_SIZE:
case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
case GL_VERTEX_ATTRIB_ARRAY_TYPE:
case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
case GL_CURRENT_VERTEX_ATTRIB:
case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
case GL_VERTEX_ATTRIB_ARRAY_POINTER:
return true;
default:
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"Unsupported vertex attrib pname: " + std::to_string(pname)));
return false;
}
}
} // namespace
SharedPtr<MG_State::GLState::VertexArrayObject> GetNamedVertexArrayObject_State(GLuint vaobj, SharedPtr<MG_State::GLState::VertexArrayObject> GetNamedVertexArrayObject_State(GLuint vaobj,
const char* caller) { const char* caller) {
if (!VertexArrayImpl::ValidateVertexArrayName(vaobj)) return nullptr; if (!VertexArrayImpl::ValidateVertexArrayName(vaobj)) return nullptr;
@@ -271,6 +327,290 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
/* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */ /* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */
void VertexAttrib1f(GLuint index, GLfloat x) {
if (!ValidateCurrentVertexAttribIndex(index, __func__)) return;
MG_State::pGLContext->SetCurrentVertexAttributeFloat(index, {x, 0.0f, 0.0f, 1.0f});
}
void VertexAttrib1fv(GLuint index, const GLfloat* v) {
if (!v) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "value pointer cannot be null."));
return;
}
VertexAttrib1f(index, v[0]);
}
void VertexAttrib2f(GLuint index, GLfloat x, GLfloat y) {
if (!ValidateCurrentVertexAttribIndex(index, __func__)) return;
MG_State::pGLContext->SetCurrentVertexAttributeFloat(index, {x, y, 0.0f, 1.0f});
}
void VertexAttrib2fv(GLuint index, const GLfloat* v) {
if (!v) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "value pointer cannot be null."));
return;
}
VertexAttrib2f(index, v[0], v[1]);
}
void VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z) {
if (!ValidateCurrentVertexAttribIndex(index, __func__)) return;
MG_State::pGLContext->SetCurrentVertexAttributeFloat(index, {x, y, z, 1.0f});
}
void VertexAttrib3fv(GLuint index, const GLfloat* v) {
if (!v) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "value pointer cannot be null."));
return;
}
VertexAttrib3f(index, v[0], v[1], v[2]);
}
void VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
if (!ValidateCurrentVertexAttribIndex(index, __func__)) return;
MG_State::pGLContext->SetCurrentVertexAttributeFloat(index, {x, y, z, w});
}
void VertexAttrib4fv(GLuint index, const GLfloat* v) {
if (!v) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "value pointer cannot be null."));
return;
}
VertexAttrib4f(index, v[0], v[1], v[2], v[3]);
}
void VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w) {
if (!ValidateCurrentVertexAttribIndex(index, __func__)) return;
MG_State::pGLContext->SetCurrentVertexAttributeInt(index, {x, y, z, w});
}
void VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w) {
if (!ValidateCurrentVertexAttribIndex(index, __func__)) return;
MG_State::pGLContext->SetCurrentVertexAttributeUint(index, {x, y, z, w});
}
void VertexAttribI4iv(GLuint index, const GLint* v) {
if (!v) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "value pointer cannot be null."));
return;
}
VertexAttribI4i(index, v[0], v[1], v[2], v[3]);
}
void VertexAttribI4uiv(GLuint index, const GLuint* v) {
if (!v) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "value pointer cannot be null."));
return;
}
VertexAttribI4ui(index, v[0], v[1], v[2], v[3]);
}
void VertexAttrib4Nub(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w) {
constexpr float kInv255 = 1.0f / 255.0f;
VertexAttrib4f(index, x * kInv255, y * kInv255, z * kInv255, w * kInv255);
}
void VertexAttrib4Nubv(GLuint index, const GLubyte* v) {
if (!v) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "value pointer cannot be null."));
return;
}
VertexAttrib4Nub(index, v[0], v[1], v[2], v[3]);
}
void VertexAttrib4ubv(GLuint index, const GLubyte* v) {
if (!v) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "value pointer cannot be null."));
return;
}
VertexAttrib4f(index, static_cast<GLfloat>(v[0]), static_cast<GLfloat>(v[1]), static_cast<GLfloat>(v[2]),
static_cast<GLfloat>(v[3]));
}
void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) {
if (!params) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "params pointer cannot be null."));
return;
}
if (!ValidateVertexAttribPname(pname)) return;
if (IsCurrentVertexAttribQuery(pname)) {
const auto& current = MG_State::pGLContext->GetCurrentVertexAttribute(index);
params[0] = current.floatValue[0];
params[1] = current.floatValue[1];
params[2] = current.floatValue[2];
params[3] = current.floatValue[3];
return;
}
const MG_State::GLState::VertexAttribute* attr = nullptr;
if (!TryGetVertexAttribute(index, &attr)) return;
switch (pname) {
case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
params[0] = attr->Enabled ? 1.0f : 0.0f;
return;
case GL_VERTEX_ATTRIB_ARRAY_SIZE:
params[0] = static_cast<GLfloat>(attr->Size);
return;
case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
params[0] = static_cast<GLfloat>(attr->Stride);
return;
case GL_VERTEX_ATTRIB_ARRAY_TYPE:
params[0] = static_cast<GLfloat>(MG_Util::ConvertDataTypeToGLEnum(attr->Type));
return;
case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
params[0] = attr->Normalized ? 1.0f : 0.0f;
return;
case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
params[0] = attr->Buffer ? static_cast<GLfloat>(attr->Buffer->GetExternalIndex()) : 0.0f;
return;
case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
params[0] = attr->IsInteger ? 1.0f : 0.0f;
return;
case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
params[0] = static_cast<GLfloat>(attr->Divisor);
return;
default:
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"Unsupported float vertex attrib pname: " + std::to_string(pname)));
return;
}
}
void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params) {
if (!params) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "params pointer cannot be null."));
return;
}
if (!ValidateVertexAttribPname(pname)) return;
if (IsCurrentVertexAttribQuery(pname)) {
const auto& current = MG_State::pGLContext->GetCurrentVertexAttribute(index);
params[0] = current.intValue[0];
params[1] = current.intValue[1];
params[2] = current.intValue[2];
params[3] = current.intValue[3];
return;
}
const MG_State::GLState::VertexAttribute* attr = nullptr;
if (!TryGetVertexAttribute(index, &attr)) return;
switch (pname) {
case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
params[0] = attr->Enabled ? GL_TRUE : GL_FALSE;
return;
case GL_VERTEX_ATTRIB_ARRAY_SIZE:
params[0] = attr->Size;
return;
case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
params[0] = attr->Stride;
return;
case GL_VERTEX_ATTRIB_ARRAY_TYPE:
params[0] = static_cast<GLint>(MG_Util::ConvertDataTypeToGLEnum(attr->Type));
return;
case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
params[0] = attr->Normalized ? GL_TRUE : GL_FALSE;
return;
case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
params[0] = attr->Buffer ? static_cast<GLint>(attr->Buffer->GetExternalIndex()) : 0;
return;
case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
params[0] = attr->IsInteger ? GL_TRUE : GL_FALSE;
return;
case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
params[0] = static_cast<GLint>(attr->Divisor);
return;
default:
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"Unsupported integer vertex attrib pname: " + std::to_string(pname)));
return;
}
}
void GetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer) {
if (!pointer) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "pointer cannot be null."));
return;
}
if (!VertexArrayImpl::ValidateVertexAttributeIndex(index)) return;
if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"pname must be GL_VERTEX_ATTRIB_ARRAY_POINTER."));
return;
}
auto& vao = MG_State::pGLContext->GetBoundVertexArray();
if (!vao) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "No vertex array object is bound."));
return;
}
const auto& attr = vao->GetAttribute(index);
*pointer = reinterpret_cast<void*>(attr.Offset);
}
void GetVertexAttribIiv(GLuint index, GLenum pname, GLint* params) {
GetVertexAttribiv(index, pname, params);
}
void GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params) {
if (!params) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "params pointer cannot be null."));
return;
}
if (!ValidateVertexAttribPname(pname)) return;
if (IsCurrentVertexAttribQuery(pname)) {
const auto& current = MG_State::pGLContext->GetCurrentVertexAttribute(index);
params[0] = current.uintValue[0];
params[1] = current.uintValue[1];
params[2] = current.uintValue[2];
params[3] = current.uintValue[3];
return;
}
GLint signedParams[4] = {};
GetVertexAttribiv(index, pname, signedParams);
params[0] = static_cast<GLuint>(signedParams[0]);
params[1] = static_cast<GLuint>(signedParams[1]);
params[2] = static_cast<GLuint>(signedParams[2]);
params[3] = static_cast<GLuint>(signedParams[3]);
}
void CreateVertexArrays(GLsizei n, GLuint* arrays) { void CreateVertexArrays(GLsizei n, GLuint* arrays) {
CreateVertexArrays_State(n, arrays); CreateVertexArrays_State(n, arrays);
} }
@@ -11,6 +11,26 @@
namespace MobileGL::MG_Impl::GLImpl { namespace MobileGL::MG_Impl::GLImpl {
/* @INSERTION_POINT:FUNCTION_DECLARATION@ */ /* @INSERTION_POINT:FUNCTION_DECLARATION@ */
void VertexAttrib1f(GLuint index, GLfloat x);
void VertexAttrib1fv(GLuint index, const GLfloat* v);
void VertexAttrib2f(GLuint index, GLfloat x, GLfloat y);
void VertexAttrib2fv(GLuint index, const GLfloat* v);
void VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z);
void VertexAttrib3fv(GLuint index, const GLfloat* v);
void VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
void VertexAttrib4fv(GLuint index, const GLfloat* v);
void VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w);
void VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
void VertexAttribI4iv(GLuint index, const GLint* v);
void VertexAttribI4uiv(GLuint index, const GLuint* v);
void VertexAttrib4Nub(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
void VertexAttrib4Nubv(GLuint index, const GLubyte* v);
void VertexAttrib4ubv(GLuint index, const GLubyte* v);
void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params);
void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params);
void GetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer);
void GetVertexAttribIiv(GLuint index, GLenum pname, GLint* params);
void GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params);
void CreateVertexArrays(GLsizei n, GLuint* arrays); void CreateVertexArrays(GLsizei n, GLuint* arrays);
void DisableVertexArrayAttrib(GLuint vaobj, GLuint index); void DisableVertexArrayAttrib(GLuint vaobj, GLuint index);
void EnableVertexArrayAttrib(GLuint vaobj, GLuint index); void EnableVertexArrayAttrib(GLuint vaobj, GLuint index);
+4
View File
@@ -35,6 +35,10 @@ namespace MobileGL::MG_Impl {
stencilTex->AllocateStorage(TextureUploadTarget::Texture2D, 0, {{512, 512, 1}, 0}); stencilTex->AllocateStorage(TextureUploadTarget::Texture2D, 0, {{512, 512, 1}, 0});
// stencilTex->SetMipmapLevel({{512, 512, 1}, 0, false, 0, {nullptr, 0}}); // stencilTex->SetMipmapLevel({{512, 512, 1}, 0, false, 0, {nullptr, 0}});
fbo0->AttachTexture(FramebufferAttachmentType::Color0, colorTex); fbo0->AttachTexture(FramebufferAttachmentType::Color0, colorTex);
fbo0->AttachTexture(FramebufferAttachmentType::FrontLeft, colorTex);
fbo0->AttachTexture(FramebufferAttachmentType::FrontRight, colorTex);
fbo0->AttachTexture(FramebufferAttachmentType::BackLeft, colorTex);
fbo0->AttachTexture(FramebufferAttachmentType::BackRight, colorTex);
fbo0->AttachTexture(FramebufferAttachmentType::Depth, depthTex); fbo0->AttachTexture(FramebufferAttachmentType::Depth, depthTex);
fbo0->AttachTexture(FramebufferAttachmentType::Stencil, stencilTex); fbo0->AttachTexture(FramebufferAttachmentType::Stencil, stencilTex);
GLImpl::FramebufferImpl::pDefaultFramebufferInfo = GLImpl::FramebufferImpl::pDefaultFramebufferInfo =
+15
View File
@@ -1139,6 +1139,21 @@ namespace MobileGL {
return EGL_NO_SURFACE; return EGL_NO_SURFACE;
} }
Bool EGLContext::IsDoubleBufferedSurface(EGLSurfaceHandle surface) const {
const std::lock_guard<std::recursive_mutex> lock(m_mutex);
const auto* surfaceObject = TryGetSurface(surface);
if (!surfaceObject) {
return false;
}
if (surfaceObject->RenderBuffer != EGL_BACK_BUFFER) {
return false;
}
return surfaceObject->Type == SurfaceType::Window ||
surfaceObject->Type == SurfaceType::PlatformWindow;
}
EGLContext::EGLSyncHandle EGLContext::CreateSync(EGLDisplayHandle display, EGLenum type, EGLContext::EGLSyncHandle EGLContext::CreateSync(EGLDisplayHandle display, EGLenum type,
const EGLAttrib* attribList) { const EGLAttrib* attribList) {
const std::lock_guard<std::recursive_mutex> lock(m_mutex); const std::lock_guard<std::recursive_mutex> lock(m_mutex);
+1
View File
@@ -87,6 +87,7 @@ namespace MobileGL {
EGLContextHandle GetCurrentContext() const; EGLContextHandle GetCurrentContext() const;
EGLDisplayHandle GetCurrentDisplay() const; EGLDisplayHandle GetCurrentDisplay() const;
EGLSurfaceHandle GetCurrentSurface(EGLint readdraw) const; EGLSurfaceHandle GetCurrentSurface(EGLint readdraw) const;
Bool IsDoubleBufferedSurface(EGLSurfaceHandle surface) const;
// Sync // Sync
EGLSyncHandle CreateSync(EGLDisplayHandle display, EGLenum type, const EGLAttrib* attribList); EGLSyncHandle CreateSync(EGLDisplayHandle display, EGLenum type, const EGLAttrib* attribList);
@@ -161,10 +161,13 @@ namespace MobileGL::MG_State::GLState {
void* BufferObject::AcquireMemory(Bool markMapped, Bool read, Bool write) { void* BufferObject::AcquireMemory(Bool markMapped, Bool read, Bool write) {
if (markMapped) { if (markMapped) {
m_isMapped = true; m_isMapped = true;
auto a = BufferMappingAccessBit::Coherent | BufferMappingAccessBit::Read;
m_mappingAccess = (read ? BufferMappingAccessBit::Read : BufferMappingAccessBit::Null) | m_mappingAccess = (read ? BufferMappingAccessBit::Read : BufferMappingAccessBit::Null) |
(write ? BufferMappingAccessBit::Write : BufferMappingAccessBit::Null); (write ? BufferMappingAccessBit::Write : BufferMappingAccessBit::Null);
m_mappedRange = {0, m_size}; m_mappedRange = {0, m_size};
if (write) {
m_change.Bits |= BufferChangeBits::ForbidInvalidationBit;
m_change.Bits |= BufferChangeBits::ForbidUnsynchronizationBit;
}
if (m_mappingAccess & BufferMappingAccessBit::Write) { if (m_mappingAccess & BufferMappingAccessBit::Write) {
m_stagingData.resize(m_size); m_stagingData.resize(m_size);
@@ -189,6 +192,13 @@ namespace MobileGL::MG_State::GLState {
m_isMapped = true; m_isMapped = true;
m_mappingAccess = access; m_mappingAccess = access;
m_mappedRange = range; m_mappedRange = range;
m_change.Bits |=
!(access & BufferMappingAccessBit::InvalidateBuffer || access & BufferMappingAccessBit::InvalidateRange)
? BufferChangeBits::ForbidInvalidationBit
: BufferChangeBits::None;
m_change.Bits |= !(access & BufferMappingAccessBit::Unsynchronized)
? BufferChangeBits::ForbidUnsynchronizationBit
: BufferChangeBits::None;
m_change.Bits |= m_change.Bits |=
!(access & BufferMappingAccessBit::InvalidateBuffer || access & BufferMappingAccessBit::InvalidateRange) !(access & BufferMappingAccessBit::InvalidateBuffer || access & BufferMappingAccessBit::InvalidateRange)
@@ -56,6 +56,14 @@ namespace MobileGL::MG_State::GLState {
bindingSlot.Bind(nullptr); bindingSlot.Bind(nullptr);
} }
} }
for (auto& bindingPointArray : m_bufferBindPointTargets) {
for (auto& bindingPoint : bindingPointArray) {
if (bindingPoint.GetBoundObject() == it->second) {
bindingPoint.Bind(nullptr);
bindingPoint.ClearRange();
}
}
}
m_bufferObjects.erase(it); m_bufferObjects.erase(it);
} }
m_indexGenerator.Delete(index); m_indexGenerator.Delete(index);
+89
View File
@@ -285,6 +285,34 @@ namespace MobileGL::MG_State {
return m_renderState.GetViewport(); return m_renderState.GetViewport();
} }
void GLContext::SetLineWidth(Float width) {
m_renderState.SetLineWidth(width);
}
Float GLContext::GetLineWidth() const {
return m_renderState.GetLineWidth();
}
void GLContext::SetPointSize(Float size) {
m_renderState.SetPointSize(size);
}
Float GLContext::GetPointSize() const {
return m_renderState.GetPointSize();
}
void GLContext::SetPolygonOffset(Float factor, Float units) {
m_renderState.SetPolygonOffset(factor, units);
}
Float GLContext::GetPolygonOffsetFactor() const {
return m_renderState.GetPolygonOffsetFactor();
}
Float GLContext::GetPolygonOffsetUnits() const {
return m_renderState.GetPolygonOffsetUnits();
}
void GLContext::SetCapability(CapabilityInput cap, Bool enabled) { void GLContext::SetCapability(CapabilityInput cap, Bool enabled) {
m_renderState.SetCapability(cap, enabled); m_renderState.SetCapability(cap, enabled);
} }
@@ -337,6 +365,14 @@ namespace MobileGL::MG_State {
m_renderState.GetBlendEquationIndexed(index, color, alpha); m_renderState.GetBlendEquationIndexed(index, color, alpha);
} }
void GLContext::SetLogicOp(LogicOperation logicOp) {
m_renderState.SetLogicOp(logicOp);
}
LogicOperation GLContext::GetLogicOp() const {
return m_renderState.GetLogicOp();
}
void GLContext::SetDepthFunc(DepthTestFunc func) { void GLContext::SetDepthFunc(DepthTestFunc func) {
m_renderState.SetDepthFunc(func); m_renderState.SetDepthFunc(func);
} }
@@ -353,6 +389,23 @@ namespace MobileGL::MG_State {
return m_renderState.GetDepthMask(); return m_renderState.GetDepthMask();
} }
void GLContext::SetStencilFunc(StencilFace face, DepthTestFunc func, Int ref, Uint32 mask) {
m_renderState.SetStencilFunc(face, func, ref, mask);
}
void GLContext::SetStencilMask(StencilFace face, Uint32 mask) {
m_renderState.SetStencilMask(face, mask);
}
void GLContext::SetStencilOp(StencilFace face, StencilOperation fail, StencilOperation depthFail,
StencilOperation depthPass) {
m_renderState.SetStencilOp(face, fail, depthFail, depthPass);
}
const StencilFaceState& GLContext::GetStencilState(StencilFace face) const {
return m_renderState.GetStencilState(face);
}
void GLContext::SetColorMask(BoolVec4 mask) { void GLContext::SetColorMask(BoolVec4 mask) {
m_renderState.SetColorMask(mask); m_renderState.SetColorMask(mask);
} }
@@ -385,6 +438,42 @@ namespace MobileGL::MG_State {
return m_renderState.GetClearStencil(); return m_renderState.GetClearStencil();
} }
void GLContext::SetBlendColor(FloatVec4 color) {
m_renderState.SetBlendColor(color);
}
const FloatVec4& GLContext::GetBlendColor() const {
return m_renderState.GetBlendColor();
}
void GLContext::SetDepthRange(FloatVec2 range) {
m_renderState.SetDepthRange(range);
}
const FloatVec2& GLContext::GetDepthRange() const {
return m_renderState.GetDepthRange();
}
void GLContext::SetSampleCoverage(Float value, Bool invert) {
m_renderState.SetSampleCoverage(value, invert);
}
Float GLContext::GetSampleCoverageValue() const {
return m_renderState.GetSampleCoverageValue();
}
Bool GLContext::GetSampleCoverageInvert() const {
return m_renderState.GetSampleCoverageInvert();
}
void GLContext::SetSampleMaskValue(Uint32 mask) {
m_renderState.SetSampleMaskValue(mask);
}
Uint32 GLContext::GetSampleMaskValue() const {
return m_renderState.GetSampleMaskValue();
}
void GLContext::SetPixelStoreParam(PixelStoreParam param, Int value) { void GLContext::SetPixelStoreParam(PixelStoreParam param, Int value) {
m_renderState.SetPixelStoreParam(param, value); m_renderState.SetPixelStoreParam(param, value);
} }
+23
View File
@@ -102,6 +102,13 @@ namespace MobileGL {
const RenderStateParameters& GetRenderStateParameters() const; const RenderStateParameters& GetRenderStateParameters() const;
void SetViewport(IntVec4 viewport); // x, y, width, height void SetViewport(IntVec4 viewport); // x, y, width, height
const IntVec4& GetViewport() const; // x, y, width, height const IntVec4& GetViewport() const; // x, y, width, height
void SetLineWidth(Float width);
Float GetLineWidth() const;
void SetPointSize(Float size);
Float GetPointSize() const;
void SetPolygonOffset(Float factor, Float units);
Float GetPolygonOffsetFactor() const;
Float GetPolygonOffsetUnits() const;
void SetCapability(CapabilityInput cap, Bool enabled); void SetCapability(CapabilityInput cap, Bool enabled);
Bool IsCapabilityEnabled(CapabilityInput cap) const; Bool IsCapabilityEnabled(CapabilityInput cap) const;
void SetCapabilityIndexed(CapabilityInput cap, Uint index, Bool enabled); void SetCapabilityIndexed(CapabilityInput cap, Uint index, Bool enabled);
@@ -117,10 +124,17 @@ namespace MobileGL {
void GetBlendEquation(BlendEquation& color, BlendEquation& alpha) const; void GetBlendEquation(BlendEquation& color, BlendEquation& alpha) const;
void SetBlendEquationIndexed(Uint index, BlendEquation color, BlendEquation alpha); void SetBlendEquationIndexed(Uint index, BlendEquation color, BlendEquation alpha);
void GetBlendEquationIndexed(Uint index, BlendEquation& color, BlendEquation& alpha) const; void GetBlendEquationIndexed(Uint index, BlendEquation& color, BlendEquation& alpha) const;
void SetLogicOp(LogicOperation logicOp);
LogicOperation GetLogicOp() const;
void SetDepthFunc(DepthTestFunc func); void SetDepthFunc(DepthTestFunc func);
DepthTestFunc GetDepthFunc() const; DepthTestFunc GetDepthFunc() const;
void SetDepthMask(Bool flag); void SetDepthMask(Bool flag);
Bool GetDepthMask() const; Bool GetDepthMask() const;
void SetStencilFunc(StencilFace face, DepthTestFunc func, Int ref, Uint32 mask);
void SetStencilMask(StencilFace face, Uint32 mask);
void SetStencilOp(StencilFace face, StencilOperation fail, StencilOperation depthFail,
StencilOperation depthPass);
const StencilFaceState& GetStencilState(StencilFace face) const;
void SetColorMask(BoolVec4 mask); void SetColorMask(BoolVec4 mask);
BoolVec4 GetColorMask() const; BoolVec4 GetColorMask() const;
void SetClearColor(FloatVec4 color); void SetClearColor(FloatVec4 color);
@@ -129,6 +143,15 @@ namespace MobileGL {
Float GetClearDepth() const; Float GetClearDepth() const;
void SetClearStencil(Int stencil); void SetClearStencil(Int stencil);
Uint32 GetClearStencil() const; Uint32 GetClearStencil() const;
void SetBlendColor(FloatVec4 color);
const FloatVec4& GetBlendColor() const;
void SetDepthRange(FloatVec2 range);
const FloatVec2& GetDepthRange() const;
void SetSampleCoverage(Float value, Bool invert);
Float GetSampleCoverageValue() const;
Bool GetSampleCoverageInvert() const;
void SetSampleMaskValue(Uint32 mask);
Uint32 GetSampleMaskValue() const;
void SetPixelStoreParam(PixelStoreParam param, Int value); void SetPixelStoreParam(PixelStoreParam param, Int value);
Int GetPixelStoreParam(PixelStoreParam param) const; Int GetPixelStoreParam(PixelStoreParam param) const;
PixelStoreParameters GetPixelStoreParameters(Bool isUnpack) const; PixelStoreParameters GetPixelStoreParameters(Bool isUnpack) const;
@@ -12,8 +12,8 @@
namespace MobileGL::MG_State::GLState { namespace MobileGL::MG_State::GLState {
// FramebufferAttachmentObject // FramebufferAttachmentObject
FramebufferAttachmentObject::FramebufferAttachmentObject( FramebufferAttachmentObject::FramebufferAttachmentObject(
const SharedPtr<MG_State::GLState::ITextureObject>& texture, Int level) const SharedPtr<MG_State::GLState::ITextureObject>& texture, TextureUploadTarget textureUploadTarget, Int level)
: m_texture(texture), m_textureLevel(level) {} : m_texture(texture), m_textureUploadTarget(textureUploadTarget), m_textureLevel(level) {}
FramebufferAttachmentObject::FramebufferAttachmentObject(const SharedPtr<RenderbufferObject>& renderbuffer) FramebufferAttachmentObject::FramebufferAttachmentObject(const SharedPtr<RenderbufferObject>& renderbuffer)
: m_renderbuffer(renderbuffer) {} : m_renderbuffer(renderbuffer) {}
FramebufferAttachmentObject::FramebufferAttachmentObject(Bool IsValid) FramebufferAttachmentObject::FramebufferAttachmentObject(Bool IsValid)
@@ -45,6 +45,10 @@ namespace MobileGL::MG_State::GLState {
return m_textureLevel; return m_textureLevel;
} }
TextureUploadTarget FramebufferAttachmentObject::GetTextureUploadTarget() const {
return m_textureUploadTarget;
}
Bool FramebufferAttachmentObject::IsComplete() const { Bool FramebufferAttachmentObject::IsComplete() const {
if (IsTexture()) { if (IsTexture()) {
Bool complete = m_texture->IsComplete(); Bool complete = m_texture->IsComplete();
@@ -59,11 +63,18 @@ namespace MobileGL::MG_State::GLState {
IntVec3 FramebufferAttachmentObject::GetSize() const { IntVec3 FramebufferAttachmentObject::GetSize() const {
if (IsTexture()) { if (IsTexture()) {
// TODO: get correct upload target
MOBILEGL_ASSERT(nullptr != static_cast<MG_State::GLState::TextureObjectMipmap*>(m_texture.get()), MOBILEGL_ASSERT(nullptr != static_cast<MG_State::GLState::TextureObjectMipmap*>(m_texture.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*>(m_texture.get()); auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(m_texture.get());
return textureMipmapObject->GetMipmapTexelSize(TextureUploadTarget::Texture2D, m_textureLevel); TextureUploadTarget resolvedTarget = m_textureUploadTarget;
if (resolvedTarget == TextureUploadTarget::Unknown) {
const auto& uploadTargets = m_texture->GetUploadTargets();
MOBILEGL_ASSERT(!uploadTargets.empty(),
"FramebufferAttachmentObject::GetSize: textureId=%u exposes no upload targets",
m_texture->GetExternalIndex());
resolvedTarget = uploadTargets[0];
}
return textureMipmapObject->GetMipmapTexelSize(resolvedTarget, m_textureLevel);
} else if (IsRenderbuffer()) { } else if (IsRenderbuffer()) {
return {m_renderbuffer->GetWidth(), m_renderbuffer->GetHeight(), 1}; return {m_renderbuffer->GetWidth(), m_renderbuffer->GetHeight(), 1};
} }
@@ -79,13 +90,16 @@ namespace MobileGL::MG_State::GLState {
: m_externalIndex(externalIndex), m_attachmentVersions{}, m_drawBuffers{} { : m_externalIndex(externalIndex), m_attachmentVersions{}, m_drawBuffers{} {
m_attachmentObjects.fill(FramebufferAttachmentObject(false)); m_attachmentObjects.fill(FramebufferAttachmentObject(false));
m_drawBuffers.fill(FramebufferAttachmentType::None); m_drawBuffers.fill(FramebufferAttachmentType::None);
m_drawBuffers[0] = FramebufferAttachmentType::Color0; const FramebufferAttachmentType defaultColorBuffer =
(externalIndex == 0) ? FramebufferAttachmentType::BackLeft : FramebufferAttachmentType::Color0;
m_drawBuffers[0] = defaultColorBuffer;
m_readBuffer = defaultColorBuffer;
m_attachmentVersions.fill(0); m_attachmentVersions.fill(0);
} }
void FramebufferObject::AttachTexture(FramebufferAttachmentType type, const SharedPtr<ITextureObject>& texture, void FramebufferObject::AttachTexture(FramebufferAttachmentType type, const SharedPtr<ITextureObject>& texture,
int level) { TextureUploadTarget textureUploadTarget, int level) {
m_attachmentObjects[static_cast<SizeT>(type)] = FramebufferAttachmentObject(texture, level); m_attachmentObjects[static_cast<SizeT>(type)] = FramebufferAttachmentObject(texture, textureUploadTarget, level);
BumpAttachmentVersion(type); BumpAttachmentVersion(type);
} }
@@ -150,6 +164,12 @@ namespace MobileGL::MG_State::GLState {
return m_drawBuffers; return m_drawBuffers;
} }
void FramebufferObject::SetReadBuffer(FramebufferAttachmentType buf) {
if (m_readBuffer == buf) return;
m_readBuffer = buf;
++m_objectVersion;
}
Uint FramebufferObject::GetExternalIndex() const { Uint FramebufferObject::GetExternalIndex() const {
return m_externalIndex; return m_externalIndex;
} }
@@ -73,6 +73,7 @@ namespace MobileGL {
class FramebufferAttachmentObject { class FramebufferAttachmentObject {
public: public:
explicit FramebufferAttachmentObject(const SharedPtr<MG_State::GLState::ITextureObject>& texture, explicit FramebufferAttachmentObject(const SharedPtr<MG_State::GLState::ITextureObject>& texture,
TextureUploadTarget textureUploadTarget,
Int level = 0); Int level = 0);
explicit FramebufferAttachmentObject(const SharedPtr<RenderbufferObject>& renderbuffer); explicit FramebufferAttachmentObject(const SharedPtr<RenderbufferObject>& renderbuffer);
explicit FramebufferAttachmentObject(Bool IsValid = true); explicit FramebufferAttachmentObject(Bool IsValid = true);
@@ -83,6 +84,7 @@ namespace MobileGL {
const SharedPtr<MG_State::GLState::ITextureObject>& GetTexture() const; const SharedPtr<MG_State::GLState::ITextureObject>& GetTexture() const;
const SharedPtr<RenderbufferObject>& GetRenderbuffer() const; const SharedPtr<RenderbufferObject>& GetRenderbuffer() const;
Int GetTextureLevel() const; Int GetTextureLevel() const;
TextureUploadTarget GetTextureUploadTarget() const;
Bool IsComplete() const; Bool IsComplete() const;
IntVec3 GetSize() const; IntVec3 GetSize() const;
Bool IsValid() const; Bool IsValid() const;
@@ -90,6 +92,7 @@ namespace MobileGL {
private: private:
SharedPtr<MG_State::GLState::ITextureObject> m_texture = nullptr; SharedPtr<MG_State::GLState::ITextureObject> m_texture = nullptr;
SharedPtr<RenderbufferObject> m_renderbuffer = nullptr; SharedPtr<RenderbufferObject> m_renderbuffer = nullptr;
TextureUploadTarget m_textureUploadTarget = TextureUploadTarget::Unknown;
Int m_textureLevel = 0; Int m_textureLevel = 0;
Bool m_isValid = true; Bool m_isValid = true;
}; };
@@ -108,7 +111,8 @@ namespace MobileGL {
FramebufferObject(Uint externalIndex); FramebufferObject(Uint externalIndex);
void AttachTexture(FramebufferAttachmentType type, const SharedPtr<ITextureObject>& texture, int level = 0); void AttachTexture(FramebufferAttachmentType type, const SharedPtr<ITextureObject>& texture,
TextureUploadTarget textureUploadTarget = TextureUploadTarget::Unknown, int level = 0);
void AttachRenderbuffer(FramebufferAttachmentType type, const SharedPtr<RenderbufferObject>& renderbuffer); void AttachRenderbuffer(FramebufferAttachmentType type, const SharedPtr<RenderbufferObject>& renderbuffer);
void Detach(FramebufferAttachmentType type); void Detach(FramebufferAttachmentType type);
const FramebufferAttachmentObject& GetAttachment(FramebufferAttachmentType type) const; const FramebufferAttachmentObject& GetAttachment(FramebufferAttachmentType type) const;
@@ -117,7 +121,7 @@ namespace MobileGL {
// aka. `buffer` as in glDrawBuffers/glReadBuffers // aka. `buffer` as in glDrawBuffers/glReadBuffers
void SetDrawBuffer(Uint index, FramebufferAttachmentType buffer); void SetDrawBuffer(Uint index, FramebufferAttachmentType buffer);
const FramebufferAttachmentArray& GetDrawBuffers() const; const FramebufferAttachmentArray& GetDrawBuffers() const;
void SetReadBuffer(FramebufferAttachmentType buf) { m_readBuffer = buf; } void SetReadBuffer(FramebufferAttachmentType buf);
FramebufferAttachmentType GetReadBuffer() const { return m_readBuffer; } FramebufferAttachmentType GetReadBuffer() const { return m_readBuffer; }
FramebufferAttachmentVersionArray GetAllFramebufferAttachmentVersions() const { FramebufferAttachmentVersionArray GetAllFramebufferAttachmentVersions() const {
@@ -127,6 +131,7 @@ namespace MobileGL {
Uint16 GetObjectVersion() const { return m_objectVersion; } Uint16 GetObjectVersion() const { return m_objectVersion; }
Uint GetExternalIndex() const; Uint GetExternalIndex() const;
Bool IsDefaultFramebuffer() const { return m_externalIndex == 0; }
private: private:
void BumpAttachmentVersion(FramebufferAttachmentType type); void BumpAttachmentVersion(FramebufferAttachmentType type);
@@ -136,7 +141,7 @@ namespace MobileGL {
FramebufferAttachmentVersionArray m_attachmentVersions; FramebufferAttachmentVersionArray m_attachmentVersions;
FramebufferAttachmentArray m_drawBuffers; // Probably no versioning needed for this, just check equality FramebufferAttachmentArray m_drawBuffers; // Probably no versioning needed for this, just check equality
FramebufferAttachmentType m_readBuffer = FramebufferAttachmentType::Color0; // ditto FramebufferAttachmentType m_readBuffer = FramebufferAttachmentType::None;
// This version will bump when draw/read buffer changes (by `glDrawBuffer(s)`/`glReadBuffer`) // This version will bump when draw/read buffer changes (by `glDrawBuffer(s)`/`glReadBuffer`)
Uint16 m_objectVersion = 0; Uint16 m_objectVersion = 0;
@@ -62,7 +62,7 @@ namespace MobileGL::MG_State::GLState {
if (it != m_framebufferObjects.end()) { if (it != m_framebufferObjects.end()) {
for (auto& bindingSlot : m_bindingSlots) { for (auto& bindingSlot : m_bindingSlots) {
if (bindingSlot.GetBoundObject() == it->second) { if (bindingSlot.GetBoundObject() == it->second) {
bindingSlot.Bind(nullptr); bindingSlot.Bind(GetFramebufferObject(0));
} }
} }
m_framebufferObjects.erase(it); m_framebufferObjects.erase(it);
@@ -60,6 +60,27 @@ namespace {
} }
namespace MobileGL::MG_State::GLState { namespace MobileGL::MG_State::GLState {
void ProgramObject::ResetLinkArtifacts() {
m_program.reset();
m_generatedSpirv.clear();
m_uniformLocations.clear();
m_uniformIndexInTProgram.clear();
m_uniformSamplerOrImageUnitIndex.clear();
m_uniformBlockIndexByName.clear();
m_uniformBlockBinding.clear();
m_uniformOffsets.clear();
m_uniformSizesInBytes.clear();
m_globalUboScratch.clear();
m_attribs.clear();
m_attribTypes.clear();
m_activeUniformCount = 0;
m_maxUniformLocation = 0;
m_uniformNameMaxLength = 0;
m_attribInNameMaxLength = 0;
m_uniformBlockNameMaxLength = 0;
m_linkStatus = false;
}
bool ProgramObject::ShaderIsAttached(const SharedPtr<ShaderObject>& shader) { bool ProgramObject::ShaderIsAttached(const SharedPtr<ShaderObject>& shader) {
MGLOG_D("ProgramObject %u: ShaderIsAttached check for shader %p", m_externalIndex, shader.get()); MGLOG_D("ProgramObject %u: ShaderIsAttached check for shader %p", m_externalIndex, shader.get());
auto it = std::find_if(m_shaders.begin(), m_shaders.end(), auto it = std::find_if(m_shaders.begin(), m_shaders.end(),
@@ -135,6 +156,8 @@ namespace MobileGL::MG_State::GLState {
void ProgramObject::Link(Bool addDefaultFSIfMissingForRenderingPipelineProgram) { void ProgramObject::Link(Bool addDefaultFSIfMissingForRenderingPipelineProgram) {
MGLOG_D("ProgramObject %u: Link start, shaders to link: %zu", m_externalIndex, m_shaders.size()); MGLOG_D("ProgramObject %u: Link start, shaders to link: %zu", m_externalIndex, m_shaders.size());
++m_backendStateVersion; ++m_backendStateVersion;
ResetLinkArtifacts();
m_infoLog.clear();
// Remove detached shaders first // Remove detached shaders first
for (const auto& detachedShader : m_detachedShaders) { for (const auto& detachedShader : m_detachedShaders) {
RemoveShader(detachedShader); RemoveShader(detachedShader);
@@ -163,7 +186,6 @@ namespace MobileGL::MG_State::GLState {
"log:\n{}\nShader src:\n{}", "log:\n{}\nShader src:\n{}",
MG_Util::ConvertGLEnumToString(shaderTypes[i]), m_shaders[i]->GetInfoLog(), MG_Util::ConvertGLEnumToString(shaderTypes[i]), m_shaders[i]->GetInfoLog(),
m_shaders[i]->GetShaderSource()); m_shaders[i]->GetShaderSource());
m_linkStatus = false;
MGLOG_E("ProgramObject %u: Link failed - shader[%zu] compile status false. InfoLog:\n%s", MGLOG_E("ProgramObject %u: Link failed - shader[%zu] compile status false. InfoLog:\n%s",
m_externalIndex, i, m_infoLog.c_str()); m_externalIndex, i, m_infoLog.c_str());
return; return;
@@ -186,9 +208,9 @@ namespace MobileGL::MG_State::GLState {
m_program = result.value(); m_program = result.value();
MGLOG_D("ProgramObject %u: LinkProgram succeeded, TProgram ptr %p", m_externalIndex, m_program.get()); MGLOG_D("ProgramObject %u: LinkProgram succeeded, TProgram ptr %p", m_externalIndex, m_program.get());
} else { } else {
m_linkStatus = false;
m_infoLog = result.error().log; m_infoLog = result.error().log;
MGLOG_E("ProgramObject %u: LinkProgram failed. InfoLog:\n%s", m_externalIndex, m_infoLog.c_str()); MGLOG_E("ProgramObject %u: LinkProgram failed. InfoLog:\n%s", m_externalIndex, m_infoLog.c_str());
return;
} }
MGLOG_D("ProgramObject %u: Starting reflection", m_externalIndex); MGLOG_D("ProgramObject %u: Starting reflection", m_externalIndex);
@@ -40,11 +40,40 @@ namespace MobileGL::MG_State::GLState {
return (Int)it->second; return (Int)it->second;
} }
Int GetActiveUniformIndex(const String& name) const {
const Int uniformIndex = m_program->getUniformIndex(name.c_str());
if (uniformIndex < 0 || uniformIndex >= m_activeUniformCount) return -1;
return m_program->getUniform(uniformIndex).name == name ? uniformIndex : -1;
}
Bool IsValidUniformLocation(Int location) const {
if (location < 0 || location > static_cast<Int>(m_maxUniformLocation)) return false;
if (static_cast<SizeT>(location) >= m_uniformIndexInTProgram.size()) return false;
const Int uniformIndexInProgram = m_uniformIndexInTProgram[location];
return uniformIndexInProgram != glslang::TQualifier::layoutLocationEnd &&
uniformIndexInProgram >= 0 && uniformIndexInProgram < m_activeUniformCount;
}
GLenum GetUniformType(Uint location) const { GLenum GetUniformType(Uint location) const {
auto& uniform = m_program->getUniform(m_uniformIndexInTProgram[location]); auto& uniform = m_program->getUniform(m_uniformIndexInTProgram[location]);
return uniform.glDefineType; return uniform.glDefineType;
} }
GLenum GetActiveUniformType(Uint index) const {
auto& uniform = m_program->getUniform(static_cast<Int>(index));
return uniform.glDefineType;
}
GLint GetActiveUniformArraySize(Uint index) const {
auto& uniform = m_program->getUniform(static_cast<Int>(index));
return uniform.size;
}
Int GetActiveUniformBlockIndex(Uint index) const {
auto& uniform = m_program->getUniform(static_cast<Int>(index));
return uniform.index;
}
const glslang::TType* GetUniformTType(Uint location) const { const glslang::TType* GetUniformTType(Uint location) const {
auto& uniform = m_program->getUniform(m_uniformIndexInTProgram[location]); auto& uniform = m_program->getUniform(m_uniformIndexInTProgram[location]);
return uniform.getType(); return uniform.getType();
@@ -56,6 +85,11 @@ namespace MobileGL::MG_State::GLState {
auto& uniform = m_program->getUniform(m_uniformIndexInTProgram[location]); auto& uniform = m_program->getUniform(m_uniformIndexInTProgram[location]);
return uniform.name; return uniform.name;
} }
const String& GetActiveUniformName(Uint index) const {
auto& uniform = m_program->getUniform(static_cast<Int>(index));
return uniform.name;
}
Uint GetUniformOffset(Uint location) const { return m_uniformOffsets[location]; } Uint GetUniformOffset(Uint location) const { return m_uniformOffsets[location]; }
Uint GetUniformSizesInBytes(Uint location) const { return MG_Util::GetGLTypeSize(GetUniformType(location)); } Uint GetUniformSizesInBytes(Uint location) const { return MG_Util::GetGLTypeSize(GetUniformType(location)); }
@@ -91,6 +125,12 @@ namespace MobileGL::MG_State::GLState {
Int GetActiveFragmentOutputCount() const { Int GetActiveFragmentOutputCount() const {
return m_program ? m_program->getNumPipeOutputs() : 0; return m_program ? m_program->getNumPipeOutputs() : 0;
} }
const String& GetActiveFragmentOutputName(Uint index) const {
MOBILEGL_ASSERT(m_program != nullptr, "ProgramObject::GetActiveFragmentOutputName: program is null");
MOBILEGL_ASSERT(index < static_cast<Uint>(m_program->getNumPipeOutputs()),
"ProgramObject::GetActiveFragmentOutputName: index=%u out of range", index);
return m_program->getPipeOutput(static_cast<Int>(index)).name;
}
Int GetFragmentOutputLocation(Uint index) const { Int GetFragmentOutputLocation(Uint index) const {
MOBILEGL_ASSERT(m_program != nullptr, "ProgramObject::GetFragmentOutputLocation: program is null"); MOBILEGL_ASSERT(m_program != nullptr, "ProgramObject::GetFragmentOutputLocation: program is null");
MOBILEGL_ASSERT(index < static_cast<Uint>(m_program->getNumPipeOutputs()), MOBILEGL_ASSERT(index < static_cast<Uint>(m_program->getNumPipeOutputs()),
@@ -98,6 +138,12 @@ namespace MobileGL::MG_State::GLState {
index); index);
return static_cast<Int>(m_program->getPipeOutput(static_cast<Int>(index)).layoutLocation()); return static_cast<Int>(m_program->getPipeOutput(static_cast<Int>(index)).layoutLocation());
} }
GLint GetActiveFragmentOutputArraySize(Uint index) const {
MOBILEGL_ASSERT(m_program != nullptr, "ProgramObject::GetActiveFragmentOutputArraySize: program is null");
MOBILEGL_ASSERT(index < static_cast<Uint>(m_program->getNumPipeOutputs()),
"ProgramObject::GetActiveFragmentOutputArraySize: index=%u out of range", index);
return m_program->getPipeOutput(static_cast<Int>(index)).size;
}
GLenum GetFragmentOutputType(Uint index) const { GLenum GetFragmentOutputType(Uint index) const {
MOBILEGL_ASSERT(m_program != nullptr, "ProgramObject::GetFragmentOutputType: program is null"); MOBILEGL_ASSERT(m_program != nullptr, "ProgramObject::GetFragmentOutputType: program is null");
MOBILEGL_ASSERT(index < static_cast<Uint>(m_program->getNumPipeOutputs()), MOBILEGL_ASSERT(index < static_cast<Uint>(m_program->getNumPipeOutputs()),
@@ -107,6 +153,9 @@ namespace MobileGL::MG_State::GLState {
} }
GLenum GetAttribType(Uint index) const { return m_attribTypes[index]; } GLenum GetAttribType(Uint index) const { return m_attribTypes[index]; }
const String& GetAttribName(Uint index) const { return m_attribs[index]; } const String& GetAttribName(Uint index) const { return m_attribs[index]; }
GLenum GetActiveAttribType(Uint index) const { return m_program->getPipeInput(static_cast<Int>(index)).glDefineType; }
GLint GetActiveAttribArraySize(Uint index) const { return m_program->getPipeInput(static_cast<Int>(index)).size; }
const String& GetActiveAttribName(Uint index) const { return m_program->getPipeInput(static_cast<Int>(index)).name; }
void* MapUBO() { return m_globalUboScratch.data(); } void* MapUBO() { return m_globalUboScratch.data(); }
const void* GetUBOData() const { return m_globalUboScratch.data(); } const void* GetUBOData() const { return m_globalUboScratch.data(); }
Uint GetUBOSize() const { return static_cast<Uint>(m_globalUboScratch.size()); } Uint GetUBOSize() const { return static_cast<Uint>(m_globalUboScratch.size()); }
@@ -126,6 +175,7 @@ namespace MobileGL::MG_State::GLState {
Int GetActiveAtomicCounterCount() const { return m_program->getNumAtomicCounters(); } Int GetActiveAtomicCounterCount() const { return m_program->getNumAtomicCounters(); }
Int GetActiveAttributesCount() const { return m_program->getNumPipeInputs(); } Int GetActiveAttributesCount() const { return m_program->getNumPipeInputs(); }
Int GetActiveUniformBlocksCount() const { return m_program->getNumUniformBlocks(); } Int GetActiveUniformBlocksCount() const { return m_program->getNumUniformBlocks(); }
GLuint GetComputeLocalSize(Uint dim) const { return m_program->getLocalSize(static_cast<Int>(dim)); }
Int GetActiveAttributesMaxLength() const { return m_attribInNameMaxLength; } Int GetActiveAttributesMaxLength() const { return m_attribInNameMaxLength; }
Int GetActiveUniformBlocksMaxNameLength() const { return m_uniformBlockNameMaxLength; } Int GetActiveUniformBlocksMaxNameLength() const { return m_uniformBlockNameMaxLength; }
Uint GetUniformBlockIndex(const char* name) const { Uint GetUniformBlockIndex(const char* name) const {
@@ -147,6 +197,16 @@ namespace MobileGL::MG_State::GLState {
return ubo.name; return ubo.name;
} }
Int GetUniformBlockActiveUniformCount(Uint index) const {
return m_program->getUniformBlock((Int)index).numMembers;
}
Bool IsUniformBlockReferencedByStage(Uint index, EShLanguage stage) const {
const auto& ubo = m_program->getUniformBlock((Int)index);
const auto stageMask = static_cast<EShLanguageMask>(1 << stage);
return (ubo.stages & stageMask) != 0;
}
// Set by glUniformBlockBinding // Set by glUniformBlockBinding
void SetUniformBlockBinding(Uint index, Uint binding) { void SetUniformBlockBinding(Uint index, Uint binding) {
if (index >= m_uniformBlockBinding.size() || m_uniformBlockBinding[index] == static_cast<Int>(binding)) { if (index >= m_uniformBlockBinding.size() || m_uniformBlockBinding[index] == static_cast<Int>(binding)) {
@@ -171,6 +231,7 @@ namespace MobileGL::MG_State::GLState {
Uint GetExternalIndex() const { return m_externalIndex; } Uint GetExternalIndex() const { return m_externalIndex; }
private: private:
void ResetLinkArtifacts();
void DoReflection(); void DoReflection();
void GenerateBinary(); void GenerateBinary();
void WaitUntilGenerationCompleted() const; void WaitUntilGenerationCompleted() const;
@@ -16,10 +16,16 @@
namespace MobileGL::MG_State::GLState { namespace MobileGL::MG_State::GLState {
void ShaderObject::SetShaderSource(const String& source) { void ShaderObject::SetShaderSource(const String& source) {
m_source = source; m_source = source;
m_shader.reset();
m_compileStatus = false;
m_infoLog.clear();
} }
void ShaderObject::SetShaderSource(String&& source) { void ShaderObject::SetShaderSource(String&& source) {
m_source = Move(source); m_source = Move(source);
m_shader.reset();
m_compileStatus = false;
m_infoLog.clear();
} }
void ShaderObject::Compile() { void ShaderObject::Compile() {
@@ -38,8 +44,10 @@ namespace MobileGL::MG_State::GLState {
if (result) { if (result) {
m_compileStatus = true; m_compileStatus = true;
m_shader = result.value(); m_shader = result.value();
m_infoLog.clear();
} else { } else {
m_compileStatus = false; m_compileStatus = false;
m_shader.reset();
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 " MGLOG_D("ShaderObject::Compile: Shader %d compilation failed.\nSource:\n%s\nInfoLog:\n%s\nSetting "
"m_compileStatus = false as a result.", "m_compileStatus = false as a result.",
@@ -12,6 +12,20 @@
namespace MobileGL { namespace MobileGL {
namespace MG_State { namespace MG_State {
namespace GLState { namespace GLState {
namespace {
SizeT GetStencilFaceIndex(StencilFace face) {
switch (face) {
case StencilFace::Front:
return 0;
case StencilFace::Back:
return 1;
default:
MOBILEGL_ASSERT(false, "Invalid stencil face enum: %d", static_cast<int>(face));
return 0;
}
}
} // namespace
RenderState::RenderState() {} RenderState::RenderState() {}
Uint RenderState::GetVersion() const { Uint RenderState::GetVersion() const {
@@ -34,6 +48,44 @@ namespace MobileGL {
return m_parameters.Viewport; return m_parameters.Viewport;
} }
void RenderState::SetLineWidth(Float width) {
if (m_parameters.LineWidth == width) return;
m_parameters.LineWidth = width;
++m_version;
}
Float RenderState::GetLineWidth() const {
return m_parameters.LineWidth;
}
void RenderState::SetPointSize(Float size) {
if (m_parameters.PointSize == size) return;
m_parameters.PointSize = size;
++m_version;
}
Float RenderState::GetPointSize() const {
return m_parameters.PointSize;
}
void RenderState::SetPolygonOffset(Float factor, Float units) {
if (m_parameters.PolygonOffsetFactor == factor && m_parameters.PolygonOffsetUnits == units) return;
m_parameters.PolygonOffsetFactor = factor;
m_parameters.PolygonOffsetUnits = units;
++m_version;
}
Float RenderState::GetPolygonOffsetFactor() const {
return m_parameters.PolygonOffsetFactor;
}
Float RenderState::GetPolygonOffsetUnits() const {
return m_parameters.PolygonOffsetUnits;
}
// -------------------- Capabilities -------------------- // -------------------- Capabilities --------------------
void RenderState::SetCapability(CapabilityInput cap, Bool enabled) { void RenderState::SetCapability(CapabilityInput cap, Bool enabled) {
#define SET_CAPABILITY(capability, flag) \ #define SET_CAPABILITY(capability, flag) \
@@ -44,9 +96,28 @@ namespace MobileGL {
break; break;
switch (cap) { switch (cap) {
SET_CAPABILITY(ColorLogicOp, enabled);
SET_CAPABILITY(DebugOutput, enabled);
SET_CAPABILITY(DebugOutputSynchronous, enabled);
SET_CAPABILITY(DepthTest, enabled); SET_CAPABILITY(DepthTest, enabled);
SET_CAPABILITY(CullFace, enabled); SET_CAPABILITY(CullFace, enabled);
SET_CAPABILITY(Dither, enabled);
SET_CAPABILITY(LineSmooth, enabled);
SET_CAPABILITY(Multisample, enabled);
SET_CAPABILITY(PolygonOffsetFill, enabled);
SET_CAPABILITY(PolygonOffsetLine, enabled);
SET_CAPABILITY(PolygonOffsetPoint, enabled);
SET_CAPABILITY(PolygonSmooth, enabled);
SET_CAPABILITY(PrimitiveRestart, enabled);
SET_CAPABILITY(PrimitiveRestartFixedIndex, enabled);
SET_CAPABILITY(RasterizerDiscard, enabled);
SET_CAPABILITY(SampleAlphaToCoverage, enabled);
SET_CAPABILITY(SampleAlphaToOne, enabled);
SET_CAPABILITY(SampleCoverage, enabled);
SET_CAPABILITY(SampleMask, enabled);
SET_CAPABILITY(ScissorTest, enabled); SET_CAPABILITY(ScissorTest, enabled);
SET_CAPABILITY(StencilTest, enabled);
SET_CAPABILITY(ProgramPointSize, enabled);
case CapabilityInput::Blend: { case CapabilityInput::Blend: {
Bool stateChanged = false; Bool stateChanged = false;
for (auto& blendState : m_parameters.BlendStates) { for (auto& blendState : m_parameters.BlendStates) {
@@ -68,9 +139,28 @@ namespace MobileGL {
case CapabilityInput::capability: \ case CapabilityInput::capability: \
return m_parameters.capability##Enabled; return m_parameters.capability##Enabled;
switch (cap) { switch (cap) {
RETURN_CAPABILITY(ColorLogicOp);
RETURN_CAPABILITY(DebugOutput);
RETURN_CAPABILITY(DebugOutputSynchronous);
RETURN_CAPABILITY(DepthTest); RETURN_CAPABILITY(DepthTest);
RETURN_CAPABILITY(CullFace); RETURN_CAPABILITY(CullFace);
RETURN_CAPABILITY(Dither);
RETURN_CAPABILITY(LineSmooth);
RETURN_CAPABILITY(Multisample);
RETURN_CAPABILITY(PolygonOffsetFill);
RETURN_CAPABILITY(PolygonOffsetLine);
RETURN_CAPABILITY(PolygonOffsetPoint);
RETURN_CAPABILITY(PolygonSmooth);
RETURN_CAPABILITY(PrimitiveRestart);
RETURN_CAPABILITY(PrimitiveRestartFixedIndex);
RETURN_CAPABILITY(RasterizerDiscard);
RETURN_CAPABILITY(SampleAlphaToCoverage);
RETURN_CAPABILITY(SampleAlphaToOne);
RETURN_CAPABILITY(SampleCoverage);
RETURN_CAPABILITY(SampleMask);
RETURN_CAPABILITY(ScissorTest); RETURN_CAPABILITY(ScissorTest);
RETURN_CAPABILITY(StencilTest);
RETURN_CAPABILITY(ProgramPointSize);
case CapabilityInput::Blend: case CapabilityInput::Blend:
return m_parameters.BlendStates[0].Enabled; return m_parameters.BlendStates[0].Enabled;
default: default:
@@ -206,6 +296,17 @@ namespace MobileGL {
alpha = m_parameters.BlendStates[index].AlphaEquation; alpha = m_parameters.BlendStates[index].AlphaEquation;
} }
void RenderState::SetLogicOp(LogicOperation logicOp) {
if (m_parameters.LogicOp == logicOp) return;
m_parameters.LogicOp = logicOp;
++m_version;
}
LogicOperation RenderState::GetLogicOp() const {
return m_parameters.LogicOp;
}
// -------------------- Depth -------------------- // -------------------- Depth --------------------
void RenderState::SetDepthFunc(DepthTestFunc func) { void RenderState::SetDepthFunc(DepthTestFunc func) {
if (m_parameters.DepthFunc == func) return; if (m_parameters.DepthFunc == func) return;
@@ -229,6 +330,42 @@ namespace MobileGL {
return m_parameters.DepthMask; return m_parameters.DepthMask;
} }
void RenderState::SetStencilFunc(StencilFace face, DepthTestFunc func, Int ref, Uint32 mask) {
StencilFaceState& state = m_parameters.StencilStates[GetStencilFaceIndex(face)];
if (state.Func == func && state.Ref == ref && state.ValueMask == mask) return;
state.Func = func;
state.Ref = ref;
state.ValueMask = mask;
++m_version;
}
void RenderState::SetStencilMask(StencilFace face, Uint32 mask) {
StencilFaceState& state = m_parameters.StencilStates[GetStencilFaceIndex(face)];
if (state.WriteMask == mask) return;
state.WriteMask = mask;
++m_version;
}
void RenderState::SetStencilOp(StencilFace face, StencilOperation fail, StencilOperation depthFail,
StencilOperation depthPass) {
StencilFaceState& state = m_parameters.StencilStates[GetStencilFaceIndex(face)];
if (state.FailOp == fail && state.PassDepthFailOp == depthFail &&
state.PassDepthPassOp == depthPass) {
return;
}
state.FailOp = fail;
state.PassDepthFailOp = depthFail;
state.PassDepthPassOp = depthPass;
++m_version;
}
const StencilFaceState& RenderState::GetStencilState(StencilFace face) const {
return m_parameters.StencilStates[GetStencilFaceIndex(face)];
}
// -------------------- Color Mask -------------------- // -------------------- Color Mask --------------------
void RenderState::SetColorMask(BoolVec4 mask) { void RenderState::SetColorMask(BoolVec4 mask) {
if (m_parameters.ColorMask == mask) return; if (m_parameters.ColorMask == mask) return;
@@ -275,6 +412,55 @@ namespace MobileGL {
return m_parameters.ClearStencil; return m_parameters.ClearStencil;
} }
void RenderState::SetBlendColor(FloatVec4 color) {
if (m_parameters.BlendColor == color) return;
m_parameters.BlendColor = color;
++m_version;
}
const FloatVec4& RenderState::GetBlendColor() const {
return m_parameters.BlendColor;
}
void RenderState::SetDepthRange(FloatVec2 range) {
if (m_parameters.DepthRange == range) return;
m_parameters.DepthRange = range;
++m_version;
}
const FloatVec2& RenderState::GetDepthRange() const {
return m_parameters.DepthRange;
}
void RenderState::SetSampleCoverage(Float value, Bool invert) {
if (m_parameters.SampleCoverageValue == value && m_parameters.SampleCoverageInvert == invert) return;
m_parameters.SampleCoverageValue = value;
m_parameters.SampleCoverageInvert = invert;
++m_version;
}
Float RenderState::GetSampleCoverageValue() const {
return m_parameters.SampleCoverageValue;
}
Bool RenderState::GetSampleCoverageInvert() const {
return m_parameters.SampleCoverageInvert;
}
void RenderState::SetSampleMaskValue(Uint32 mask) {
if (m_parameters.SampleMaskValue == mask) return;
m_parameters.SampleMaskValue = mask;
++m_version;
}
Uint32 RenderState::GetSampleMaskValue() const {
return m_parameters.SampleMaskValue;
}
// -------------------- Pixel Store -------------------- // -------------------- Pixel Store --------------------
void RenderState::SetPixelStoreParam(PixelStoreParam param, Int value) { void RenderState::SetPixelStoreParam(PixelStoreParam param, Int value) {
#define SET_PIXEL_STORE_PARAM(paramNameHead, paramNameTail, val) \ #define SET_PIXEL_STORE_PARAM(paramNameHead, paramNameTail, val) \
@@ -41,6 +41,27 @@ namespace MobileGL {
Unknown = -1 Unknown = -1
}; };
enum class LogicOperation {
Clear,
And,
AndReverse,
Copy,
AndInverted,
Noop,
Xor,
Or,
Nor,
Equiv,
Invert,
OrReverse,
CopyInverted,
OrInverted,
Nand,
Set,
LogicOperationCount,
Unknown = -1
};
enum class DepthTestFunc { enum class DepthTestFunc {
Never, Never,
Less, Less,
@@ -54,6 +75,26 @@ namespace MobileGL {
Unknown = -1 Unknown = -1
}; };
enum class StencilOperation {
Keep,
Zero,
Replace,
IncrementClamp,
DecrementClamp,
Invert,
IncrementWrap,
DecrementWrap,
StencilOperationCount,
Unknown = -1
};
enum class StencilFace {
Front,
Back,
StencilFaceCount,
Unknown = -1
};
enum class PixelStoreParam { enum class PixelStoreParam {
// Pack Parameters // Pack Parameters
PackAlignment, PackAlignment,
@@ -162,12 +203,27 @@ namespace MobileGL {
BlendEquation AlphaEquation = BlendEquation::Add; BlendEquation AlphaEquation = BlendEquation::Add;
}; };
struct StencilFaceState {
DepthTestFunc Func = DepthTestFunc::Always;
Int Ref = 0;
Uint32 ValueMask = 0xffffffffu;
Uint32 WriteMask = 0xffffffffu;
StencilOperation FailOp = StencilOperation::Keep;
StencilOperation PassDepthFailOp = StencilOperation::Keep;
StencilOperation PassDepthPassOp = StencilOperation::Keep;
};
struct RenderStateParameters { struct RenderStateParameters {
// Rasterization // Rasterization
IntVec4 Viewport = IntVec4(0, 0, 0, 0); // x, y, width, height IntVec4 Viewport = IntVec4(0, 0, 0, 0); // x, y, width, height
Float LineWidth = 1.0f;
Float PointSize = 1.0f;
Float PolygonOffsetFactor = 0.0f;
Float PolygonOffsetUnits = 0.0f;
// Blending // Blending
Array<PerBufferBlendState, MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS> BlendStates; Array<PerBufferBlendState, MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS> BlendStates;
LogicOperation LogicOp = LogicOperation::Copy;
// Depth // Depth
Bool DepthTestEnabled = false; Bool DepthTestEnabled = false;
@@ -181,6 +237,12 @@ namespace MobileGL {
FloatVec4 ClearColor = FloatVec4(0.0f, 0.0f, 0.0f, 1.0f); FloatVec4 ClearColor = FloatVec4(0.0f, 0.0f, 0.0f, 1.0f);
Float ClearDepth = 1.0f; Float ClearDepth = 1.0f;
Uint32 ClearStencil = 0; Uint32 ClearStencil = 0;
FloatVec4 BlendColor = FloatVec4(0.0f, 0.0f, 0.0f, 0.0f);
FloatVec2 DepthRange = FloatVec2(0.0f, 1.0f);
Float SampleCoverageValue = 1.0f;
Bool SampleCoverageInvert = false;
Uint32 SampleMaskValue = 0xffffffffu;
Array<StencilFaceState, 2> StencilStates{};
// Cull Face // Cull Face
Bool CullFaceEnabled = false; Bool CullFaceEnabled = false;
@@ -189,7 +251,26 @@ namespace MobileGL {
ProvokingVertexMode ProvokingVertexModeSetting = ProvokingVertexMode::LastVertex; ProvokingVertexMode ProvokingVertexModeSetting = ProvokingVertexMode::LastVertex;
// Scissor // Scissor
Bool ColorLogicOpEnabled = false;
Bool DebugOutputEnabled = false;
Bool DebugOutputSynchronousEnabled = false;
Bool DitherEnabled = true;
Bool LineSmoothEnabled = false;
Bool MultisampleEnabled = true;
Bool PolygonOffsetFillEnabled = false;
Bool PolygonOffsetLineEnabled = false;
Bool PolygonOffsetPointEnabled = false;
Bool PolygonSmoothEnabled = false;
Bool PrimitiveRestartEnabled = false;
Bool PrimitiveRestartFixedIndexEnabled = false;
Bool RasterizerDiscardEnabled = false;
Bool SampleAlphaToCoverageEnabled = false;
Bool SampleAlphaToOneEnabled = false;
Bool SampleCoverageEnabled = false;
Bool SampleMaskEnabled = false;
Bool ScissorTestEnabled = false; Bool ScissorTestEnabled = false;
Bool StencilTestEnabled = false;
Bool ProgramPointSizeEnabled = false;
IntVec4 ScissorBox = IntVec4(0, 0, 0, 0); // x, y, width, height IntVec4 ScissorBox = IntVec4(0, 0, 0, 0); // x, y, width, height
}; };
@@ -205,6 +286,13 @@ namespace MobileGL {
// Rasterization // Rasterization
void SetViewport(IntVec4 viewport); // x, y, width, height void SetViewport(IntVec4 viewport); // x, y, width, height
const IntVec4& GetViewport() const; // x, y, width, height const IntVec4& GetViewport() const; // x, y, width, height
void SetLineWidth(Float width);
Float GetLineWidth() const;
void SetPointSize(Float size);
Float GetPointSize() const;
void SetPolygonOffset(Float factor, Float units);
Float GetPolygonOffsetFactor() const;
Float GetPolygonOffsetUnits() const;
// Capabilities // Capabilities
void SetCapability(CapabilityInput cap, Bool enabled); void SetCapability(CapabilityInput cap, Bool enabled);
@@ -224,12 +312,19 @@ namespace MobileGL {
void GetBlendEquation(BlendEquation& color, BlendEquation& alpha) const; void GetBlendEquation(BlendEquation& color, BlendEquation& alpha) const;
void SetBlendEquationIndexed(Uint index, BlendEquation color, BlendEquation alpha); void SetBlendEquationIndexed(Uint index, BlendEquation color, BlendEquation alpha);
void GetBlendEquationIndexed(Uint index, BlendEquation& color, BlendEquation& alpha) const; void GetBlendEquationIndexed(Uint index, BlendEquation& color, BlendEquation& alpha) const;
void SetLogicOp(LogicOperation logicOp);
LogicOperation GetLogicOp() const;
// Depth // Depth
void SetDepthFunc(DepthTestFunc func); void SetDepthFunc(DepthTestFunc func);
DepthTestFunc GetDepthFunc() const; DepthTestFunc GetDepthFunc() const;
void SetDepthMask(Bool flag); void SetDepthMask(Bool flag);
Bool GetDepthMask() const; Bool GetDepthMask() const;
void SetStencilFunc(StencilFace face, DepthTestFunc func, Int ref, Uint32 mask);
void SetStencilMask(StencilFace face, Uint32 mask);
void SetStencilOp(StencilFace face, StencilOperation fail, StencilOperation depthFail,
StencilOperation depthPass);
const StencilFaceState& GetStencilState(StencilFace face) const;
// Color Mask // Color Mask
void SetColorMask(BoolVec4 mask); void SetColorMask(BoolVec4 mask);
@@ -242,6 +337,15 @@ namespace MobileGL {
Float GetClearDepth() const; Float GetClearDepth() const;
void SetClearStencil(Int stencil); void SetClearStencil(Int stencil);
Uint32 GetClearStencil() const; Uint32 GetClearStencil() const;
void SetBlendColor(FloatVec4 color);
const FloatVec4& GetBlendColor() const;
void SetDepthRange(FloatVec2 range);
const FloatVec2& GetDepthRange() const;
void SetSampleCoverage(Float value, Bool invert);
Float GetSampleCoverageValue() const;
Bool GetSampleCoverageInvert() const;
void SetSampleMaskValue(Uint32 mask);
Uint32 GetSampleMaskValue() const;
// Pixel Store // Pixel Store
void SetPixelStoreParam(PixelStoreParam param, Int value); void SetPixelStoreParam(PixelStoreParam param, Int value);
@@ -76,6 +76,10 @@ namespace MobileGL {
m_height = size.y(); m_height = size.y();
m_allocated = true; m_allocated = true;
} }
void RenderbufferObject::SetSamples(Int samples) {
m_samples = samples;
}
} // namespace GLState } // namespace GLState
} // namespace MG_State } // namespace MG_State
} // namespace MobileGL } // namespace MobileGL
@@ -29,6 +29,7 @@ namespace MobileGL {
Uint GetExternalIndex() const; Uint GetExternalIndex() const;
void SetInternalFormat(TextureInternalFormat format); void SetInternalFormat(TextureInternalFormat format);
void AllocateStorage(IntVec2 size); void AllocateStorage(IntVec2 size);
void SetSamples(Int samples);
Int GetWidth() const; Int GetWidth() const;
Int GetHeight() const; Int GetHeight() const;
TextureInternalFormat GetInternalFormat() const; TextureInternalFormat GetInternalFormat() const;
@@ -47,7 +48,7 @@ namespace MobileGL {
TextureInternalFormat m_internalFormat; TextureInternalFormat m_internalFormat;
Int m_width = 0; Int m_width = 0;
Int m_height = 0; Int m_height = 0;
Int m_samples = 0; // TODO: multisampling support Int m_samples = 0;
Bool m_allocated = false; Bool m_allocated = false;
ComponentSizes m_componentSizes; ComponentSizes m_componentSizes;
}; };
@@ -57,10 +57,6 @@ namespace MobileGL {
void SamplerObject::SetLodRange(Float minLod, Float maxLod) { void SamplerObject::SetLodRange(Float minLod, Float maxLod) {
if (minLod == m_samplerParameters.minLod && maxLod == m_samplerParameters.maxLod) return; if (minLod == m_samplerParameters.minLod && maxLod == m_samplerParameters.maxLod) return;
if (minLod > maxLod) {
THROW_EXCEPTION("minLod cannot be greater than maxLod");
}
m_samplerParameters.minLod = minLod; m_samplerParameters.minLod = minLod;
m_samplerParameters.maxLod = maxLod; m_samplerParameters.maxLod = maxLod;
++m_version; ++m_version;
@@ -13,9 +13,15 @@
namespace MobileGL { namespace MobileGL {
namespace MG_State { namespace MG_State {
namespace GLState { namespace GLState {
static std::atomic<Uint64> s_nextTextureLifetimeId = 1;
// TextureObjectBase implementations // TextureObjectBase implementations
Uint64 TextureObjectBase::AllocateLifetimeId() {
return s_nextTextureLifetimeId.fetch_add(1, std::memory_order_relaxed);
}
TextureObjectBase::TextureObjectBase(TextureTarget target, Uint externalIndex) TextureObjectBase::TextureObjectBase(TextureTarget target, Uint externalIndex)
: m_target(target), m_externalIndex(externalIndex) { : m_externalIndex(externalIndex), m_lifetimeId(AllocateLifetimeId()), m_target(target) {
m_sampler = MakeShared<SamplerObject>(0); m_sampler = MakeShared<SamplerObject>(0);
} }
@@ -139,6 +145,26 @@ namespace MobileGL {
return m_textureParamsVersion; return m_textureParamsVersion;
} }
Int TextureObjectBase::GetSamples() const {
return m_samples;
}
void TextureObjectBase::SetSamples(Int samples) {
m_samples = samples;
}
Bool TextureObjectBase::HasFixedSampleLocations() const {
return m_fixedSampleLocations;
}
void TextureObjectBase::SetFixedSampleLocations(Bool fixedSampleLocations) {
m_fixedSampleLocations = fixedSampleLocations;
}
Uint64 TextureObjectBase::GetLifetimeId() const {
return m_lifetimeId;
}
Uint TextureObjectWithOneMipmap::GetMipmapLevelCount() const { Uint TextureObjectWithOneMipmap::GetMipmapLevelCount() const {
return m_textureStorage.GetLevelCount(); return m_textureStorage.GetLevelCount();
} }
@@ -40,6 +40,11 @@ namespace MobileGL::MG_State::GLState {
virtual void SetBaseLevel(Uint baseLevel) = 0; virtual void SetBaseLevel(Uint baseLevel) = 0;
virtual void SetMaxLevel(Uint maxLevel) = 0; virtual void SetMaxLevel(Uint maxLevel) = 0;
virtual Uint16 GetTextureParamsVersion() const = 0; virtual Uint16 GetTextureParamsVersion() const = 0;
virtual Int GetSamples() const = 0;
virtual void SetSamples(Int samples) = 0;
virtual Bool HasFixedSampleLocations() const = 0;
virtual void SetFixedSampleLocations(Bool fixedSampleLocations) = 0;
virtual Uint64 GetLifetimeId() const = 0;
protected: protected:
virtual Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const = 0; virtual Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const = 0;
@@ -67,9 +72,17 @@ namespace MobileGL::MG_State::GLState {
void SetBaseLevel(Uint baseLevel) override; void SetBaseLevel(Uint baseLevel) override;
void SetMaxLevel(Uint maxLevel) override; void SetMaxLevel(Uint maxLevel) override;
Uint16 GetTextureParamsVersion() const override; Uint16 GetTextureParamsVersion() const override;
Int GetSamples() const override;
void SetSamples(Int samples) override;
Bool HasFixedSampleLocations() const override;
void SetFixedSampleLocations(Bool fixedSampleLocations) override;
Uint64 GetLifetimeId() const override;
protected: protected:
static Uint64 AllocateLifetimeId();
const Uint m_externalIndex; const Uint m_externalIndex;
const Uint64 m_lifetimeId;
const TextureTarget m_target = TextureTarget::Unknown; const TextureTarget m_target = TextureTarget::Unknown;
TextureInternalFormat m_internalFormat = TextureInternalFormat::Unknown; TextureInternalFormat m_internalFormat = TextureInternalFormat::Unknown;
SharedPtr<SamplerObject> m_sampler = nullptr; SharedPtr<SamplerObject> m_sampler = nullptr;
@@ -78,6 +91,8 @@ namespace MobileGL::MG_State::GLState {
TextureSwizzleParam::Blue, TextureSwizzleParam::Alpha}; TextureSwizzleParam::Blue, TextureSwizzleParam::Alpha};
UintVec2 m_levelRange = {0, 1000}; UintVec2 m_levelRange = {0, 1000};
Uint16 m_textureParamsVersion = 0; Uint16 m_textureParamsVersion = 0;
Int m_samples = 0;
Bool m_fixedSampleLocations = true;
}; };
class TextureObjectMipmap : public TextureObjectBase { class TextureObjectMipmap : public TextureObjectBase {
@@ -50,7 +50,7 @@ namespace MobileGL {
Uint TextureObject2DCube::GetIndexOfTextureUploadTarget(TextureUploadTarget target) const { Uint TextureObject2DCube::GetIndexOfTextureUploadTarget(TextureUploadTarget target) const {
MOBILEGL_ASSERT(TextureUploadTarget::CubeMapPositiveX <= target && MOBILEGL_ASSERT(TextureUploadTarget::CubeMapPositiveX <= target &&
target <= TextureUploadTarget::ProxyCubeMap, target <= TextureUploadTarget::CubeMapNegativeZ,
"Invalid TextureUploadTarget!"); "Invalid TextureUploadTarget!");
return (Uint)target - (Uint)TextureUploadTarget::CubeMapPositiveX; return (Uint)target - (Uint)TextureUploadTarget::CubeMapPositiveX;
} }
@@ -15,12 +15,11 @@ namespace MobileGL {
namespace GLState { namespace GLState {
/* These texture types are not yet implemented: /* These texture types are not yet implemented:
* TextureRectangle, * TextureRectangle,
* Texture2DMultisample,
* TextureBuffer, * TextureBuffer,
* Texture1DArray, * Texture1DArray,
* Texture2DArray, * Texture2DArray,
* TextureCubeMapArray, * TextureCubeMapArray,
* Texture2DMultisampleArray * Texture2DMultisampleArray layered attachment behavior
*/ */
#define STUB_TEXTURE_OBJECT_CLASS_DEFINITION(className, texTarget, uploadTargets) \ #define STUB_TEXTURE_OBJECT_CLASS_DEFINITION(className, texTarget, uploadTargets) \
class className : public TextureObjectWithOneMipmap { \ class className : public TextureObjectWithOneMipmap { \
@@ -57,7 +57,7 @@ namespace MobileGL::MG_State::GLState {
textureObject = MakeShared<TextureObjectBuffer>(index); textureObject = MakeShared<TextureObjectBuffer>(index);
break; break;
// These texture types are stubbed: // These texture types are still stubbed:
case TextureTarget::TextureRectangle: case TextureTarget::TextureRectangle:
textureObject = MakeShared<TextureObjectRectangle>(index); textureObject = MakeShared<TextureObjectRectangle>(index);
break; break;
@@ -50,8 +50,8 @@ namespace MobileGL::MG_State::GLState {
void VertexArrayState::MarkVertexArrayForDeletion(Uint index) { void VertexArrayState::MarkVertexArrayForDeletion(Uint index) {
if (m_indexGenerator.IsValid(index)) { if (m_indexGenerator.IsValid(index)) {
if (m_boundVertexArray) { if (m_boundVertexArray && m_boundVertexArray->GetExternalIndex() == index) {
m_boundVertexArray = nullptr; m_boundVertexArray = GetVertexArrayObject(0);
} }
if (ValidateVertexArrayObject(index)) { if (ValidateVertexArrayObject(index)) {
@@ -46,6 +46,8 @@ TEST(DirectVulkanSanity, WindowCreation) {
#include <EGL/egl.h> #include <EGL/egl.h>
#ifdef _WIN32 #ifdef _WIN32
#define GLFW_EXPOSE_NATIVE_WIN32 #define GLFW_EXPOSE_NATIVE_WIN32
#elif defined(__linux__)
#define GLFW_EXPOSE_NATIVE_X11
#elif defined(__APPLE__) #elif defined(__APPLE__)
#define GLFW_EXPOSE_NATIVE_COCOA #define GLFW_EXPOSE_NATIVE_COCOA
#endif #endif
@@ -74,9 +76,11 @@ TEST(DirectVulkanSanity, ContextCreation) {
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
GLFWwindow* window = glfwCreateWindow(800, 600, "MobileGL ContextCreation", nullptr, nullptr); GLFWwindow* window = glfwCreateWindow(800, 600, "MobileGL ContextCreation", nullptr, nullptr);
EGLNativeWindowType nativewindow = nullptr; EGLNativeWindowType nativewindow = 0;
#ifdef _WIN32 #ifdef _WIN32
nativewindow = glfwGetWin32Window(window); nativewindow = glfwGetWin32Window(window);
#elif defined(__linux__)
nativewindow = static_cast<EGLNativeWindowType>(glfwGetX11Window(window));
#elif defined(__APPLE__) #elif defined(__APPLE__)
void* cocoaWindow = glfwGetCocoaWindow(window); void* cocoaWindow = glfwGetCocoaWindow(window);
ASSERT_NE(cocoaWindow, nullptr); ASSERT_NE(cocoaWindow, nullptr);
@@ -95,6 +99,7 @@ TEST(DirectVulkanSanity, ContextCreation) {
msgSendVoidObj(contentView, sel_registerName("setLayer:"), metalLayer); msgSendVoidObj(contentView, sel_registerName("setLayer:"), metalLayer);
nativewindow = reinterpret_cast<EGLNativeWindowType>(metalLayer); nativewindow = reinterpret_cast<EGLNativeWindowType>(metalLayer);
#endif #endif
ASSERT_NE(nativewindow, static_cast<EGLNativeWindowType>(0));
EGLSurface surface = eglCreateWindowSurface(display, config, nativewindow, nullptr); EGLSurface surface = eglCreateWindowSurface(display, config, nativewindow, nullptr);
eglMakeCurrent(display, surface, surface, context); eglMakeCurrent(display, surface, surface, context);
@@ -28,6 +28,8 @@
#include <EGL/egl.h> #include <EGL/egl.h>
#ifdef _WIN32 #ifdef _WIN32
#define GLFW_EXPOSE_NATIVE_WIN32 #define GLFW_EXPOSE_NATIVE_WIN32
#elif defined(__linux__)
#define GLFW_EXPOSE_NATIVE_X11
#elif defined(__APPLE__) #elif defined(__APPLE__)
#define GLFW_EXPOSE_NATIVE_COCOA #define GLFW_EXPOSE_NATIVE_COCOA
#endif #endif
@@ -107,9 +109,11 @@ int main() {
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
GLFWwindow* window = glfwCreateWindow(800, 600, "MobileGL ContextCreation", nullptr, nullptr); GLFWwindow* window = glfwCreateWindow(800, 600, "MobileGL ContextCreation", nullptr, nullptr);
EGLNativeWindowType nativewindow = nullptr; EGLNativeWindowType nativewindow = 0;
#ifdef _WIN32 #ifdef _WIN32
nativewindow = glfwGetWin32Window(window); nativewindow = glfwGetWin32Window(window);
#elif defined(__linux__)
nativewindow = static_cast<EGLNativeWindowType>(glfwGetX11Window(window));
#elif defined(__APPLE__) #elif defined(__APPLE__)
void* cocoaWindow = glfwGetCocoaWindow(window); void* cocoaWindow = glfwGetCocoaWindow(window);
MOBILEGL_ASSERT(cocoaWindow, "glfwGetCocoaWindow returned null"); MOBILEGL_ASSERT(cocoaWindow, "glfwGetCocoaWindow returned null");
@@ -128,6 +132,7 @@ int main() {
msgSendVoidObj(contentView, sel_registerName("setLayer:"), metalLayer); msgSendVoidObj(contentView, sel_registerName("setLayer:"), metalLayer);
nativewindow = reinterpret_cast<EGLNativeWindowType>(metalLayer); nativewindow = reinterpret_cast<EGLNativeWindowType>(metalLayer);
#endif #endif
MOBILEGL_ASSERT(nativewindow, "Failed to acquire native window handle for EGL window surface creation");
EGLSurface surface = eglCreateWindowSurface(display, config, nativewindow, nullptr); EGLSurface surface = eglCreateWindowSurface(display, config, nativewindow, nullptr);
eglMakeCurrent(display, surface, surface, context); eglMakeCurrent(display, surface, surface, context);
@@ -105,6 +105,20 @@ TEST_F(FramebufferTest, CreateFramebuffersCreatesObjectsImmediately) {
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR); EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
} }
TEST_F(FramebufferTest, DefaultFramebufferIdentityTracksFramebufferNameZero) {
const auto defaultFramebuffer = MG_State::pGLContext->GetFramebufferObject(0);
ASSERT_NE(defaultFramebuffer, nullptr);
EXPECT_TRUE(defaultFramebuffer->IsDefaultFramebuffer());
const auto defaultFramebufferCopy = *defaultFramebuffer;
EXPECT_TRUE(defaultFramebufferCopy.IsDefaultFramebuffer());
GLuint framebuffer = 0;
MG_Impl::GLImpl::CreateFramebuffers(1, &framebuffer);
const auto userFramebuffer = MG_State::pGLContext->GetFramebufferObject(framebuffer);
ASSERT_NE(userFramebuffer, nullptr);
EXPECT_FALSE(userFramebuffer->IsDefaultFramebuffer());
}
TEST_F(FramebufferTest, NamedFramebufferTextureAttachesWithoutChangingBindings) { TEST_F(FramebufferTest, NamedFramebufferTextureAttachesWithoutChangingBindings) {
GLuint framebuffer = 0; GLuint framebuffer = 0;
MG_Impl::GLImpl::CreateFramebuffers(1, &framebuffer); MG_Impl::GLImpl::CreateFramebuffers(1, &framebuffer);
@@ -150,6 +164,27 @@ TEST_F(FramebufferTest, NamedDepthFramebufferTextureStorageIsCompleteWithoutBind
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR); EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
} }
TEST_F(FramebufferTest, FramebufferTextureBumpsAttachmentVersionOnlyOnce) {
GLuint framebuffer = 0;
GLuint texture = 0;
MG_Impl::GLImpl::CreateFramebuffers(1, &framebuffer);
MG_Impl::GLImpl::CreateTextures(GL_TEXTURE_2D, 1, &texture);
MG_Impl::GLImpl::TextureStorage2D(texture, 1, GL_RGBA8, 64, 32);
MG_Impl::GLImpl::BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
const auto framebufferObject = MG_State::pGLContext->GetFramebufferObject(framebuffer);
const auto beforeVersions = framebufferObject->GetAllFramebufferAttachmentVersions();
const auto beforeObjectVersion = framebufferObject->GetObjectVersion();
MG_Impl::GLImpl::FramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0);
const auto afterVersions = framebufferObject->GetAllFramebufferAttachmentVersions();
EXPECT_EQ(afterVersions[static_cast<SizeT>(FramebufferAttachmentType::Color0)],
beforeVersions[static_cast<SizeT>(FramebufferAttachmentType::Color0)] + 1);
EXPECT_EQ(framebufferObject->GetObjectVersion(), beforeObjectVersion + 1);
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
}
TEST_F(FramebufferTest, ReadPixelsAllowsPersistentMappedPixelPackBuffer) { TEST_F(FramebufferTest, ReadPixelsAllowsPersistentMappedPixelPackBuffer) {
GLuint framebuffer = 0; GLuint framebuffer = 0;
GLuint texture = 0; GLuint texture = 0;
@@ -238,6 +273,46 @@ TEST_F(FramebufferTest, NamedFramebufferDrawBuffersDoNotModifyDefaultFramebuffer
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR); EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
} }
TEST_F(FramebufferTest, DefaultFramebufferReadBufferAcceptsGLBackAlias) {
const auto defaultRead =
MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject();
MG_Impl::GLImpl::ReadBuffer(GL_BACK);
EXPECT_EQ(defaultRead->GetReadBuffer(), FramebufferAttachmentType::BackLeft);
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
}
TEST_F(FramebufferTest, DefaultFramebufferDrawBufferAcceptsGLFrontAlias) {
const auto defaultDraw =
MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
MG_Impl::GLImpl::DrawBuffer(GL_FRONT);
EXPECT_EQ(defaultDraw->GetDrawBuffers()[0], FramebufferAttachmentType::FrontLeft);
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
}
TEST_F(FramebufferTest, DefaultFramebufferProvidesTextureAttachmentsForFrontAndBackAliases) {
const auto defaultFramebuffer =
MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
ASSERT_NE(defaultFramebuffer, nullptr);
const auto& frontLeft = defaultFramebuffer->GetAttachment(FramebufferAttachmentType::FrontLeft);
const auto& frontRight = defaultFramebuffer->GetAttachment(FramebufferAttachmentType::FrontRight);
const auto& backLeft = defaultFramebuffer->GetAttachment(FramebufferAttachmentType::BackLeft);
const auto& backRight = defaultFramebuffer->GetAttachment(FramebufferAttachmentType::BackRight);
EXPECT_TRUE(frontLeft.IsTexture());
EXPECT_TRUE(frontRight.IsTexture());
EXPECT_TRUE(backLeft.IsTexture());
EXPECT_TRUE(backRight.IsTexture());
EXPECT_TRUE(frontLeft.IsComplete());
EXPECT_TRUE(frontRight.IsComplete());
EXPECT_TRUE(backLeft.IsComplete());
EXPECT_TRUE(backRight.IsComplete());
}
TEST_F(FramebufferTest, ClearNamedFramebufferfvUsesNamedObjectWithoutChangingBindings) { TEST_F(FramebufferTest, ClearNamedFramebufferfvUsesNamedObjectWithoutChangingBindings) {
GLuint framebuffer = 0; GLuint framebuffer = 0;
MG_Impl::GLImpl::CreateFramebuffers(1, &framebuffer); MG_Impl::GLImpl::CreateFramebuffers(1, &framebuffer);
+12
View File
@@ -165,6 +165,18 @@ TEST(DirectVulkanSanity, AdvertisesTextureStorageForDirectStateAccess) {
EXPECT_NE(std::find(extensions.begin(), extensions.end(), MobileGL::E_GL_ARB_texture_storage), extensions.end()); EXPECT_NE(std::find(extensions.begin(), extensions.end(), MobileGL::E_GL_ARB_texture_storage), extensions.end());
} }
TEST(DirectVulkanSanity, RenderPassExtentUsesSwapchainSizeOnlyForDefaultFramebuffer) {
using MobileGL::MG_Backend::DirectVulkan::ResolveRenderPassFramebufferExtent;
const MobileGL::TextureSize attachmentExtent = {512, 512, 1};
const VkExtent2D swapchainExtent = {3200u, 1440u};
EXPECT_EQ(ResolveRenderPassFramebufferExtent(true, attachmentExtent, swapchainExtent),
MobileGL::IntVec2(3200, 1440));
EXPECT_EQ(ResolveRenderPassFramebufferExtent(false, attachmentExtent, swapchainExtent),
MobileGL::IntVec2(512, 512));
}
TEST(DirectVulkanSanity, AdvertisesVoxyRequiredRenderingExtensionsWithoutRaisingGLVersion) { TEST(DirectVulkanSanity, AdvertisesVoxyRequiredRenderingExtensionsWithoutRaisingGLVersion) {
MobileGL::MG_Backend::DirectVulkan::BackendObject_DirectVulkan backend; MobileGL::MG_Backend::DirectVulkan::BackendObject_DirectVulkan backend;
const auto& rendererInfo = backend.GetRendererInfo().RendererGLInfo; const auto& rendererInfo = backend.GetRendererInfo().RendererGLInfo;
+18
View File
@@ -18,3 +18,21 @@ target_link_libraries(
include(GoogleTest) include(GoogleTest)
gtest_discover_tests(TextureTest) gtest_discover_tests(TextureTest)
add_executable(
VkClearManagerTest
VkClearManagerTest.cpp
)
target_include_directories(VkClearManagerTest PRIVATE
${MGL_ROOT}/include
${MGL_ROOT}/MobileGL
)
target_link_libraries(
VkClearManagerTest PRIVATE
GTest::gtest_main
${LINK_LIBRARIES}
)
gtest_discover_tests(VkClearManagerTest)
+153
View File
@@ -99,6 +99,57 @@ TEST_F(TextureTest, BoundTexSubImage2DUsesCompactRowsAfterUnpackProcessing) {
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR); EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
} }
TEST_F(TextureTest, BoundTexStorage2DAllocatesRedTextureForSubImageUpdates) {
GLuint texture = 0;
MG_Impl::GLImpl::GenTextures(1, &texture);
MG_Impl::GLImpl::BindTexture(GL_TEXTURE_2D, texture);
MG_Impl::GLImpl::TexStorage2D(GL_TEXTURE_2D, 1, GL_R8, 32, 32);
const auto textureObject = MG_State::pGLContext->GetTextureObject(texture);
auto* mipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
ASSERT_NE(mipmapObject, nullptr);
EXPECT_EQ(mipmapObject->GetMipmapTexelSize(TextureUploadTarget::Texture2D, 0), IntVec3(32, 32, 1));
EXPECT_TRUE(textureObject->IsComplete());
const Uint8 pixels[4 * 4] = {
1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16,
};
MG_Impl::GLImpl::TexSubImage2D(GL_TEXTURE_2D, 0, 20, 28, 4, 4, GL_RED, GL_UNSIGNED_BYTE, pixels);
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
}
TEST_F(TextureTest, TextureStorage2DMultisampleTracksNamedObjectState) {
GLuint texture = 0;
MG_Impl::GLImpl::CreateTextures(GL_TEXTURE_2D_MULTISAMPLE, 1, &texture);
MG_Impl::GLImpl::TextureStorage2DMultisample(texture, 4, GL_RGBA8, 8, 6, GL_TRUE);
const auto textureObject = MG_State::pGLContext->GetTextureObject(texture);
ASSERT_NE(textureObject, nullptr);
EXPECT_EQ(textureObject->GetTarget(), TextureTarget::Texture2DMultisample);
EXPECT_EQ(textureObject->GetSamples(), 4);
EXPECT_TRUE(textureObject->HasFixedSampleLocations());
auto* textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
ASSERT_NE(textureMipmapObject, nullptr);
EXPECT_EQ(textureMipmapObject->GetMipmapLevelCount(), 1u);
EXPECT_EQ(textureMipmapObject->GetMipmapTexelSize(TextureUploadTarget::Texture2DMultisample, 0), IntVec3(8, 6, 1));
EXPECT_FALSE(textureMipmapObject->IsStorageDirty(TextureUploadTarget::Texture2DMultisample, 0));
GLint samples = 0;
GLint fixed = 0;
MG_Impl::GLImpl::GetTextureLevelParameteriv(texture, 0, GL_TEXTURE_SAMPLES, &samples);
MG_Impl::GLImpl::GetTextureLevelParameteriv(texture, 0, GL_TEXTURE_FIXED_SAMPLE_LOCATIONS, &fixed);
EXPECT_EQ(samples, 4);
EXPECT_EQ(fixed, GL_TRUE);
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
}
TEST_F(TextureTest, GetTextureImageReadsNamedObjectWithoutBinding) { TEST_F(TextureTest, GetTextureImageReadsNamedObjectWithoutBinding) {
GLuint texture = 0; GLuint texture = 0;
MG_Impl::GLImpl::CreateTextures(GL_TEXTURE_2D, 1, &texture); MG_Impl::GLImpl::CreateTextures(GL_TEXTURE_2D, 1, &texture);
@@ -208,6 +259,108 @@ TEST_F(TextureTest, TextureParameterfModifiesNamedObjectWithoutBinding) {
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR); EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
} }
TEST_F(TextureTest, TextureStorage1DAndSubImageModifyNamedObjectOnly) {
GLuint namedTexture = 0;
GLuint boundTexture = 0;
MG_Impl::GLImpl::CreateTextures(GL_TEXTURE_1D, 1, &namedTexture);
MG_Impl::GLImpl::CreateTextures(GL_TEXTURE_1D, 1, &boundTexture);
MG_Impl::GLImpl::BindTextureUnit(0, boundTexture);
const auto boundObjectBefore =
MG_State::pGLContext->GetTextureUnitObject(0).GetBindingSlot(TextureTarget::Texture1D).GetBoundObject();
MG_Impl::GLImpl::TextureStorage1D(namedTexture, 2, GL_RGBA8, 4);
const Uint8 pixels[] = {
1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16,
};
MG_Impl::GLImpl::TextureSubImage1D(namedTexture, 0, 0, 4, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
const auto textureObject = MG_State::pGLContext->GetTextureObject(namedTexture);
auto* mipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
ASSERT_NE(mipmapObject, nullptr);
EXPECT_EQ(mipmapObject->GetMipmapTexelSize(TextureUploadTarget::Texture1D, 0), IntVec3(4, 1, 1));
EXPECT_EQ(mipmapObject->GetMipmapTexelSize(TextureUploadTarget::Texture1D, 1), IntVec3(2, 1, 1));
EXPECT_TRUE(mipmapObject->IsStorageDirty(TextureUploadTarget::Texture1D, 0));
const auto* stored = static_cast<const Uint8*>(mipmapObject->MapMipmapData(TextureUploadTarget::Texture1D, 0));
ASSERT_NE(stored, nullptr);
EXPECT_EQ(std::memcmp(stored, pixels, sizeof(pixels)), 0);
EXPECT_EQ(MG_State::pGLContext->GetTextureUnitObject(0).GetBindingSlot(TextureTarget::Texture1D).GetBoundObject(),
boundObjectBefore);
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
}
TEST_F(TextureTest, TextureStorage3DAndSubImageModifyNamedObjectOnly) {
GLuint texture = 0;
MG_Impl::GLImpl::CreateTextures(GL_TEXTURE_3D, 1, &texture);
MG_Impl::GLImpl::TextureStorage3D(texture, 2, GL_R8, 2, 2, 2);
const Uint8 pixels[] = {
1, 2, 3, 4,
5, 6, 7, 8,
};
MG_Impl::GLImpl::TextureSubImage3D(texture, 0, 0, 0, 0, 2, 2, 2, GL_RED, GL_UNSIGNED_BYTE, pixels);
const auto textureObject = MG_State::pGLContext->GetTextureObject(texture);
auto* mipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
ASSERT_NE(mipmapObject, nullptr);
EXPECT_EQ(mipmapObject->GetMipmapTexelSize(TextureUploadTarget::Texture3D, 0), IntVec3(2, 2, 2));
EXPECT_EQ(mipmapObject->GetMipmapTexelSize(TextureUploadTarget::Texture3D, 1), IntVec3(1, 1, 1));
EXPECT_TRUE(mipmapObject->IsStorageDirty(TextureUploadTarget::Texture3D, 0));
const auto* stored = static_cast<const Uint8*>(mipmapObject->MapMipmapData(TextureUploadTarget::Texture3D, 0));
ASSERT_NE(stored, nullptr);
EXPECT_EQ(std::memcmp(stored, pixels, sizeof(pixels)), 0);
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
}
TEST_F(TextureTest, NamedTextureVectorParametersAndGettersWorkWithoutBinding) {
GLuint texture = 0;
MG_Impl::GLImpl::CreateTextures(GL_TEXTURE_2D, 1, &texture);
const GLfloat borderColor[] = {0.25f, 0.5f, 0.75f, 1.0f};
const GLint swizzle[] = {GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA};
MG_Impl::GLImpl::TextureParameterfv(texture, GL_TEXTURE_BORDER_COLOR, borderColor);
MG_Impl::GLImpl::TextureParameterIiv(texture, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
GLfloat reportedBorder[4] = {};
GLint reportedSwizzle[4] = {};
MG_Impl::GLImpl::GetTextureParameterfv(texture, GL_TEXTURE_BORDER_COLOR, reportedBorder);
MG_Impl::GLImpl::GetTextureParameterIiv(texture, GL_TEXTURE_SWIZZLE_RGBA, reportedSwizzle);
EXPECT_FLOAT_EQ(reportedBorder[0], borderColor[0]);
EXPECT_FLOAT_EQ(reportedBorder[1], borderColor[1]);
EXPECT_FLOAT_EQ(reportedBorder[2], borderColor[2]);
EXPECT_FLOAT_EQ(reportedBorder[3], borderColor[3]);
EXPECT_EQ(reportedSwizzle[0], GL_BLUE);
EXPECT_EQ(reportedSwizzle[1], GL_GREEN);
EXPECT_EQ(reportedSwizzle[2], GL_RED);
EXPECT_EQ(reportedSwizzle[3], GL_ALPHA);
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
}
TEST_F(TextureTest, GetInternalformativReportsBasicTextureMetadata) {
GLint params[4] = {};
MG_Impl::GLImpl::GetInternalformativ(GL_TEXTURE_2D, GL_RGBA8, GL_INTERNALFORMAT_SUPPORTED, 1, params);
EXPECT_EQ(params[0], GL_TRUE);
MG_Impl::GLImpl::GetInternalformativ(GL_TEXTURE_2D, GL_RGBA8, GL_TEXTURE_IMAGE_FORMAT, 1, params);
EXPECT_EQ(params[0], GL_RGBA);
MG_Impl::GLImpl::GetInternalformativ(GL_TEXTURE_2D, GL_RGBA8, GL_TEXTURE_IMAGE_TYPE, 1, params);
EXPECT_EQ(params[0], GL_UNSIGNED_BYTE);
MG_Impl::GLImpl::GetInternalformativ(GL_TEXTURE_3D, GL_DEPTH24_STENCIL8, GL_FRAMEBUFFER_RENDERABLE_LAYERED, 1,
params);
EXPECT_EQ(params[0], GL_FULL_SUPPORT);
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
}
TEST_F(TextureTest, NormalizeDepth24Stencil8UsesPackedDepthStencilType) { TEST_F(TextureTest, NormalizeDepth24Stencil8UsesPackedDepthStencilType) {
GLenum internalFormat = 0; GLenum internalFormat = 0;
GLenum format = 0; GLenum format = 0;
@@ -0,0 +1,110 @@
// MobileGL - MobileGL/MG_Test/Texture/VkClearManagerTest.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 <gtest/gtest.h>
#include "Includes.h"
#include "Init.h"
#include <MG_Backend/DirectVulkan/Renderer/VkClearManager.h>
#include <MG_Impl/GLImpl/Texture/GL_Texture.h>
#include <MG_State/GLState/Core.h>
using namespace MobileGL;
using namespace MobileGL::MG_Backend::DirectVulkan;
class VkClearManagerTest : public ::testing::Test {
protected:
void SetUp() override { MobileGL::Initialize(); }
};
TEST_F(VkClearManagerTest, CollectGarbageRemovesExpiredTexturesAndTheirPendingClears) {
VkClearManager clearManager;
ASSERT_TRUE(clearManager.Initialize());
constexpr SizeT kTextureCount = 64;
Vector<GLuint> textureNames(kTextureCount, 0);
Vector<PendingClearKey> pendingKeys;
pendingKeys.reserve(kTextureCount);
const ClearAttachmentPayload clearPayload{
.mask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT,
.color = FloatVec4(0.25f, 0.5f, 0.75f, 1.0f),
.depth = 0.5f,
};
for (SizeT i = 0; i < kTextureCount; ++i) {
MG_Impl::GLImpl::CreateTextures(GL_TEXTURE_2D, 1, &textureNames[i]);
ASSERT_NE(textureNames[i], 0u);
{
const auto textureObject = MG_State::pGLContext->GetTextureObject(textureNames[i]);
ASSERT_NE(textureObject, nullptr);
const PendingClearKey key = VkClearManager::MakePendingClearKey(textureObject.get());
clearManager.QueueClear(clearPayload, textureObject);
EXPECT_TRUE(clearManager.HasPendingClear(key));
pendingKeys.emplace_back(key);
}
}
MG_Impl::GLImpl::DeleteTextures(static_cast<GLsizei>(textureNames.size()), textureNames.data());
for (Int i = 0; i < 255; ++i) {
EXPECT_EQ(clearManager.CollectGarbage(), 0u);
}
EXPECT_EQ(clearManager.CollectGarbage(), kTextureCount);
ClearAttachmentPayload outPayload{};
for (const auto& key : pendingKeys) {
EXPECT_FALSE(clearManager.HasPendingClear(key));
EXPECT_FALSE(clearManager.GetPendingClear(key, outPayload));
}
GLuint freshTexture = 0;
MG_Impl::GLImpl::CreateTextures(GL_TEXTURE_2D, 1, &freshTexture);
ASSERT_NE(freshTexture, 0u);
const auto freshTextureObject = MG_State::pGLContext->GetTextureObject(freshTexture);
ASSERT_NE(freshTextureObject, nullptr);
EXPECT_FALSE(clearManager.HasPendingClear(freshTextureObject.get()));
MG_Impl::GLImpl::DeleteTextures(1, &freshTexture);
clearManager.Shutdown();
}
TEST_F(VkClearManagerTest, StalePendingClearsAreRejectedBeforePeriodicGarbageCollection) {
VkClearManager clearManager;
ASSERT_TRUE(clearManager.Initialize());
GLuint texture = 0;
MG_Impl::GLImpl::CreateTextures(GL_TEXTURE_2D, 1, &texture);
ASSERT_NE(texture, 0u);
PendingClearKey key{};
{
const auto textureObject = MG_State::pGLContext->GetTextureObject(texture);
ASSERT_NE(textureObject, nullptr);
key = VkClearManager::MakePendingClearKey(textureObject.get());
clearManager.QueueClear(ClearAttachmentPayload{
.mask = GL_COLOR_BUFFER_BIT,
.color = FloatVec4(1.0f, 0.25f, 0.5f, 0.75f),
}, textureObject);
EXPECT_TRUE(clearManager.HasPendingClear(key));
}
MG_Impl::GLImpl::DeleteTextures(1, &texture);
ClearAttachmentPayload outPayload{};
EXPECT_FALSE(clearManager.HasPendingClear(key));
EXPECT_FALSE(clearManager.GetPendingClear(key, outPayload));
EXPECT_FALSE(clearManager.HasPendingClear(key));
clearManager.Shutdown();
}
@@ -41,11 +41,11 @@ namespace MobileGL::MG_Util::BackendLoader {
#endif #endif
} }
Bool AcquireGLESFunctions(MG_External::GLESFunctionsTable& funcs, void AcquireGLESFunctions(MG_External::GLESFunctionsTable& funcs,
MG_External::EGL::eglGetProcAddress_PTR procAddress) { MG_External::EGL::eglGetProcAddress_PTR procAddress) {
if (!procAddress) { if (!procAddress) {
MGLOG_E("eglGetProcAddress is nullptr, cannot load GLES functions"); MGLOG_E("eglGetProcAddress is nullptr, cannot load GLES functions");
return false; return;
} }
#define INIT_GLES_FUNC(name) \ #define INIT_GLES_FUNC(name) \
@@ -149,6 +149,8 @@ namespace MobileGL::MG_Util::BackendLoader {
INIT_GLES_FUNC(glIsTexture) INIT_GLES_FUNC(glIsTexture)
INIT_GLES_FUNC(glLineWidth) INIT_GLES_FUNC(glLineWidth)
INIT_GLES_FUNC(glLinkProgram) INIT_GLES_FUNC(glLinkProgram)
INIT_GLES_FUNC(glLogicOp)
INIT_GLES_FUNC(glPointSize)
INIT_GLES_FUNC(glPixelStorei) INIT_GLES_FUNC(glPixelStorei)
INIT_GLES_FUNC(glPolygonOffset) INIT_GLES_FUNC(glPolygonOffset)
INIT_GLES_FUNC(glReadPixels) INIT_GLES_FUNC(glReadPixels)
@@ -428,16 +430,16 @@ namespace MobileGL::MG_Util::BackendLoader {
INIT_GLES_FUNC(glMultiDrawElementsIndirectEXT) INIT_GLES_FUNC(glMultiDrawElementsIndirectEXT)
INIT_GLES_FUNC(glMultiDrawElementsBaseVertexEXT) INIT_GLES_FUNC(glMultiDrawElementsBaseVertexEXT)
} }
return true;
} }
Bool AcquireEGLFunctions(MG_External::EGLFunctionsTable& funcs) { void AcquireEGLFunctions(MG_External::EGLFunctionsTable& funcs) {
static const Vector<String> EGLLibNames = {"libEGL.so"}; static const Vector<String> EGLLibNames = {"libEGL.so"};
void* eglLib = OpenLib(EGLLibNames); void* eglLib = OpenLib(EGLLibNames);
if (!eglLib) { if (!eglLib) {
MGLOG_E("Failed to open libEGL.so"); MGLOG_E("Failed to open libEGL.so");
return false; return;
} }
#define INIT_EGL_FUNC(name) \ #define INIT_EGL_FUNC(name) \
do { \ do { \
funcs.name = (MG_External::EGL::name##_PTR)ProcAddress(eglLib, #name); \ funcs.name = (MG_External::EGL::name##_PTR)ProcAddress(eglLib, #name); \
@@ -495,7 +497,6 @@ namespace MobileGL::MG_Util::BackendLoader {
INIT_EGL_FUNC(eglGetPlatformDisplay) INIT_EGL_FUNC(eglGetPlatformDisplay)
INIT_EGL_FUNC(eglWaitSync) INIT_EGL_FUNC(eglWaitSync)
} }
return true;
} }
Bool FillInGLESCapabilities(MG_External::GLESCapabilities& caps, const MG_External::GLESFunctionsTable& glesFuncs) { Bool FillInGLESCapabilities(MG_External::GLESCapabilities& caps, const MG_External::GLESFunctionsTable& glesFuncs) {
@@ -535,6 +536,179 @@ namespace MobileGL::MG_Util::BackendLoader {
MGLOG_I("OpenGL ES capabilities:"); MGLOG_I("OpenGL ES capabilities:");
glesFuncs.glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &caps.UniformBufferOffsetAlignment); glesFuncs.glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &caps.UniformBufferOffsetAlignment);
MGLOG_I(" GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: %d", caps.UniformBufferOffsetAlignment); MGLOG_I(" GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: %d", caps.UniformBufferOffsetAlignment);
GLfloat aliasedLineWidthRange[2] = {1.0f, 1.0f};
GLfloat smoothLineWidthRange[2] = {1.0f, 1.0f};
GLfloat smoothLineWidthGranularity = 1.0f;
GLfloat aliasedPointSizeRange[2] = {1.0f, 1.0f};
GLfloat viewportBoundsRange[2] = {0.0f, 0.0f};
GLint maxViewportDims[2] = {16384, 16384};
GLint viewportSubpixelBits = 0;
GLint max3DTextureSize = 16384;
GLint maxArrayTextureLayers = 2048;
GLint maxCubeMapTextureSize = 16384;
GLint maxFramebufferWidth = 16384;
GLint maxFramebufferHeight = 16384;
GLint maxFramebufferLayers = 2048;
GLint maxRenderbufferSize = 16384;
GLint maxTextureSize = 16384;
GLint maxColorTextureSamples = 1;
GLint maxDepthTextureSamples = 1;
GLint maxFramebufferSamples = 1;
GLint maxIntegerSamples = 1;
GLint maxSamples = 1;
GLint maxSampleMaskWords = 1;
GLint maxTextureImageUnits = 32;
GLint maxVertexTextureImageUnits = 32;
GLint maxComputeTextureImageUnits = 32;
GLint maxCombinedTextureImageUnits = 192;
GLint maxVertexAttribs = 16;
GLint maxComputeShaderStorageBlocks = 8;
GLint maxCombinedShaderStorageBlocks = 32;
GLint maxComputeUniformBlocks = 12;
GLint maxComputeWorkGroupInvocations = 128;
GLint maxShaderStorageBufferBindings = 8;
GLint maxTextureBufferSize = 65536;
GLint maxUniformBufferBindings = 24;
GLint maxUniformBlockSize = 16384;
GLint maxImageUnits = 8;
GLint maxCombinedImageUniforms = 8;
GLint maxComputeImageUniforms = 8;
GLint maxDrawBuffers = 8;
GLint maxColorAttachments = 8;
GLint maxClipDistances = 8;
GLint maxViewports = 16;
glesFuncs.glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, aliasedLineWidthRange);
glesFuncs.glGetFloatv(GL_SMOOTH_LINE_WIDTH_RANGE, smoothLineWidthRange);
glesFuncs.glGetFloatv(GL_SMOOTH_LINE_WIDTH_GRANULARITY, &smoothLineWidthGranularity);
glesFuncs.glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, aliasedPointSizeRange);
glesFuncs.glGetFloatv(GL_VIEWPORT_BOUNDS_RANGE, viewportBoundsRange);
glesFuncs.glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &max3DTextureSize);
glesFuncs.glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxArrayTextureLayers);
glesFuncs.glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &maxCubeMapTextureSize);
glesFuncs.glGetIntegerv(GL_MAX_FRAMEBUFFER_WIDTH, &maxFramebufferWidth);
glesFuncs.glGetIntegerv(GL_MAX_FRAMEBUFFER_HEIGHT, &maxFramebufferHeight);
glesFuncs.glGetIntegerv(GL_MAX_FRAMEBUFFER_LAYERS, &maxFramebufferLayers);
glesFuncs.glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &maxRenderbufferSize);
glesFuncs.glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
glesFuncs.glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &maxColorTextureSamples);
glesFuncs.glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &maxDepthTextureSamples);
glesFuncs.glGetIntegerv(GL_MAX_FRAMEBUFFER_SAMPLES, &maxFramebufferSamples);
glesFuncs.glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &maxIntegerSamples);
glesFuncs.glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
glesFuncs.glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &maxSampleMaskWords);
glesFuncs.glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
glesFuncs.glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxVertexTextureImageUnits);
glesFuncs.glGetIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &maxComputeTextureImageUnits);
glesFuncs.glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxCombinedTextureImageUnits);
glesFuncs.glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
glesFuncs.glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &maxComputeShaderStorageBlocks);
glesFuncs.glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &maxCombinedShaderStorageBlocks);
glesFuncs.glGetIntegerv(GL_MAX_COMPUTE_UNIFORM_BLOCKS, &maxComputeUniformBlocks);
glesFuncs.glGetIntegerv(GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS, &maxComputeWorkGroupInvocations);
glesFuncs.glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &maxShaderStorageBufferBindings);
glesFuncs.glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &maxTextureBufferSize);
glesFuncs.glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &maxUniformBufferBindings);
glesFuncs.glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize);
glesFuncs.glGetIntegerv(GL_MAX_IMAGE_UNITS, &maxImageUnits);
glesFuncs.glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &maxCombinedImageUniforms);
glesFuncs.glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
glesFuncs.glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
glesFuncs.glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxColorAttachments);
glesFuncs.glGetIntegerv(GL_MAX_CLIP_DISTANCES, &maxClipDistances);
glesFuncs.glGetIntegerv(GL_MAX_VIEWPORTS, &maxViewports);
glesFuncs.glGetIntegerv(GL_MAX_VIEWPORT_DIMS, maxViewportDims);
glesFuncs.glGetIntegerv(GL_VIEWPORT_SUBPIXEL_BITS, &viewportSubpixelBits);
caps.AliasedLineWidthRangeMin = aliasedLineWidthRange[0];
caps.AliasedLineWidthRangeMax = aliasedLineWidthRange[1];
caps.SmoothLineWidthRangeMin = smoothLineWidthRange[0];
caps.SmoothLineWidthRangeMax = smoothLineWidthRange[1];
caps.SmoothLineWidthGranularity = smoothLineWidthGranularity;
caps.PointSizeRangeMin = aliasedPointSizeRange[0];
caps.PointSizeRangeMax = aliasedPointSizeRange[1];
caps.PointSizeGranularity = 1.0f;
caps.Max3DTextureSize = max3DTextureSize;
caps.MaxArrayTextureLayers = maxArrayTextureLayers;
caps.MaxCubeMapTextureSize = maxCubeMapTextureSize;
caps.MaxFramebufferWidth = maxFramebufferWidth;
caps.MaxFramebufferHeight = maxFramebufferHeight;
caps.MaxFramebufferLayers = maxFramebufferLayers;
caps.MaxRenderbufferSize = maxRenderbufferSize;
caps.MaxTextureSize = maxTextureSize;
caps.MaxColorTextureSamples = maxColorTextureSamples;
caps.MaxDepthTextureSamples = maxDepthTextureSamples;
caps.MaxFramebufferSamples = maxFramebufferSamples;
caps.MaxIntegerSamples = maxIntegerSamples;
caps.MaxSamples = maxSamples;
caps.MaxSampleMaskWords = maxSampleMaskWords;
caps.MaxTextureImageUnits = maxTextureImageUnits;
caps.MaxVertexTextureImageUnits = maxVertexTextureImageUnits;
caps.MaxComputeTextureImageUnits = maxComputeTextureImageUnits;
caps.MaxCombinedTextureImageUnits = maxCombinedTextureImageUnits;
caps.MaxVertexAttribs = maxVertexAttribs;
caps.MaxComputeShaderStorageBlocks = maxComputeShaderStorageBlocks;
caps.MaxCombinedShaderStorageBlocks = maxCombinedShaderStorageBlocks;
caps.MaxComputeUniformBlocks = maxComputeUniformBlocks;
caps.MaxComputeWorkGroupInvocations = maxComputeWorkGroupInvocations;
caps.MaxShaderStorageBufferBindings = maxShaderStorageBufferBindings;
caps.MaxTextureBufferSize = maxTextureBufferSize;
caps.MaxUniformBufferBindings = maxUniformBufferBindings;
caps.MaxUniformBlockSize = maxUniformBlockSize;
caps.MaxImageUnits = maxImageUnits;
caps.MaxCombinedImageUniforms = maxCombinedImageUniforms;
caps.MaxComputeImageUniforms = maxComputeImageUniforms;
caps.MaxDrawBuffers = maxDrawBuffers;
caps.MaxColorAttachments = maxColorAttachments;
caps.MaxClipDistances = maxClipDistances;
caps.MaxViewports = maxViewports;
caps.MaxViewportWidth = maxViewportDims[0];
caps.MaxViewportHeight = maxViewportDims[1];
caps.ViewportBoundsRangeMin = viewportBoundsRange[0];
caps.ViewportBoundsRangeMax = viewportBoundsRange[1];
caps.ViewportSubpixelBits = viewportSubpixelBits;
MGLOG_I(" GL_ALIASED_LINE_WIDTH_RANGE: [%.3f, %.3f]", caps.AliasedLineWidthRangeMin,
caps.AliasedLineWidthRangeMax);
MGLOG_I(" GL_SMOOTH_LINE_WIDTH_RANGE: [%.3f, %.3f]", caps.SmoothLineWidthRangeMin,
caps.SmoothLineWidthRangeMax);
MGLOG_I(" GL_SMOOTH_LINE_WIDTH_GRANULARITY: %.3f", caps.SmoothLineWidthGranularity);
MGLOG_I(" GL_ALIASED_POINT_SIZE_RANGE: [%.3f, %.3f]", caps.PointSizeRangeMin, caps.PointSizeRangeMax);
MGLOG_I(" GL_MAX_3D_TEXTURE_SIZE: %d", caps.Max3DTextureSize);
MGLOG_I(" GL_MAX_ARRAY_TEXTURE_LAYERS: %d", caps.MaxArrayTextureLayers);
MGLOG_I(" GL_MAX_CUBE_MAP_TEXTURE_SIZE: %d", caps.MaxCubeMapTextureSize);
MGLOG_I(" GL_MAX_FRAMEBUFFER_WIDTH: %d", caps.MaxFramebufferWidth);
MGLOG_I(" GL_MAX_FRAMEBUFFER_HEIGHT: %d", caps.MaxFramebufferHeight);
MGLOG_I(" GL_MAX_FRAMEBUFFER_LAYERS: %d", caps.MaxFramebufferLayers);
MGLOG_I(" GL_MAX_RENDERBUFFER_SIZE: %d", caps.MaxRenderbufferSize);
MGLOG_I(" GL_MAX_TEXTURE_SIZE: %d", caps.MaxTextureSize);
MGLOG_I(" GL_MAX_COLOR_TEXTURE_SAMPLES: %d", caps.MaxColorTextureSamples);
MGLOG_I(" GL_MAX_DEPTH_TEXTURE_SAMPLES: %d", caps.MaxDepthTextureSamples);
MGLOG_I(" GL_MAX_FRAMEBUFFER_SAMPLES: %d", caps.MaxFramebufferSamples);
MGLOG_I(" GL_MAX_INTEGER_SAMPLES: %d", caps.MaxIntegerSamples);
MGLOG_I(" GL_MAX_SAMPLES: %d", caps.MaxSamples);
MGLOG_I(" GL_MAX_SAMPLE_MASK_WORDS: %d", caps.MaxSampleMaskWords);
MGLOG_I(" GL_MAX_TEXTURE_IMAGE_UNITS: %d", caps.MaxTextureImageUnits);
MGLOG_I(" GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: %d", caps.MaxVertexTextureImageUnits);
MGLOG_I(" GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS: %d", caps.MaxComputeTextureImageUnits);
MGLOG_I(" GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: %d", caps.MaxCombinedTextureImageUnits);
MGLOG_I(" GL_MAX_VERTEX_ATTRIBS: %d", caps.MaxVertexAttribs);
MGLOG_I(" GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS: %d", caps.MaxComputeShaderStorageBlocks);
MGLOG_I(" GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS: %d", caps.MaxCombinedShaderStorageBlocks);
MGLOG_I(" GL_MAX_COMPUTE_UNIFORM_BLOCKS: %d", caps.MaxComputeUniformBlocks);
MGLOG_I(" GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS: %d", caps.MaxComputeWorkGroupInvocations);
MGLOG_I(" GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS: %d", caps.MaxShaderStorageBufferBindings);
MGLOG_I(" GL_MAX_TEXTURE_BUFFER_SIZE: %d", caps.MaxTextureBufferSize);
MGLOG_I(" GL_MAX_UNIFORM_BUFFER_BINDINGS: %d", caps.MaxUniformBufferBindings);
MGLOG_I(" GL_MAX_UNIFORM_BLOCK_SIZE: %d", caps.MaxUniformBlockSize);
MGLOG_I(" GL_MAX_IMAGE_UNITS: %d", caps.MaxImageUnits);
MGLOG_I(" GL_MAX_COMBINED_IMAGE_UNIFORMS: %d", caps.MaxCombinedImageUniforms);
MGLOG_I(" GL_MAX_COMPUTE_IMAGE_UNIFORMS: %d", caps.MaxComputeImageUniforms);
MGLOG_I(" GL_MAX_DRAW_BUFFERS: %d", caps.MaxDrawBuffers);
MGLOG_I(" GL_MAX_COLOR_ATTACHMENTS: %d", caps.MaxColorAttachments);
MGLOG_I(" GL_MAX_CLIP_DISTANCES: %d", caps.MaxClipDistances);
MGLOG_I(" GL_MAX_VIEWPORTS: %d", caps.MaxViewports);
MGLOG_I(" GL_MAX_VIEWPORT_DIMS: [%d, %d]", caps.MaxViewportWidth, caps.MaxViewportHeight);
MGLOG_I(" GL_VIEWPORT_BOUNDS_RANGE: [%.3f, %.3f]", caps.ViewportBoundsRangeMin,
caps.ViewportBoundsRangeMax);
MGLOG_I(" GL_VIEWPORT_SUBPIXEL_BITS: %d", caps.ViewportSubpixelBits);
return true; return true;
} }
@@ -238,6 +238,8 @@ namespace MobileGL {
GL_FUNC_TYPEDEF(GLboolean, glIsTexture, GLuint texture) GL_FUNC_TYPEDEF(GLboolean, glIsTexture, GLuint texture)
GL_FUNC_TYPEDEF(void, glLineWidth, GLfloat width) GL_FUNC_TYPEDEF(void, glLineWidth, GLfloat width)
GL_FUNC_TYPEDEF(void, glLinkProgram, GLuint program) GL_FUNC_TYPEDEF(void, glLinkProgram, GLuint program)
GL_FUNC_TYPEDEF(void, glLogicOp, GLenum opcode)
GL_FUNC_TYPEDEF(void, glPointSize, GLfloat size)
GL_FUNC_TYPEDEF(void, glPixelStorei, GLenum pname, GLint param) GL_FUNC_TYPEDEF(void, glPixelStorei, GLenum pname, GLint param)
GL_FUNC_TYPEDEF(void, glPolygonOffset, GLfloat factor, GLfloat units) GL_FUNC_TYPEDEF(void, glPolygonOffset, GLfloat factor, GLfloat units)
GL_FUNC_TYPEDEF(void, glReadPixels, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GL_FUNC_TYPEDEF(void, glReadPixels, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
@@ -725,6 +727,8 @@ namespace MobileGL {
GL_FUNC_DECL(glIsTexture) GL_FUNC_DECL(glIsTexture)
GL_FUNC_DECL(glLineWidth) GL_FUNC_DECL(glLineWidth)
GL_FUNC_DECL(glLinkProgram) GL_FUNC_DECL(glLinkProgram)
GL_FUNC_DECL(glLogicOp)
GL_FUNC_DECL(glPointSize)
GL_FUNC_DECL(glPixelStorei) GL_FUNC_DECL(glPixelStorei)
GL_FUNC_DECL(glPolygonOffset) GL_FUNC_DECL(glPolygonOffset)
GL_FUNC_DECL(glReadPixels) GL_FUNC_DECL(glReadPixels)
@@ -1015,13 +1019,60 @@ namespace MobileGL {
Bool SupportsPersistentMapping = false; Bool SupportsPersistentMapping = false;
Bool SupportsNorm16Texture = false; Bool SupportsNorm16Texture = false;
Int UniformBufferOffsetAlignment = 256; Int UniformBufferOffsetAlignment = 256;
Float AliasedLineWidthRangeMin = 1.0f;
Float AliasedLineWidthRangeMax = 1.0f;
Float SmoothLineWidthRangeMin = 1.0f;
Float SmoothLineWidthRangeMax = 1.0f;
Float SmoothLineWidthGranularity = 1.0f;
Float PointSizeRangeMin = 1.0f;
Float PointSizeRangeMax = 1.0f;
Float PointSizeGranularity = 1.0f;
Int Max3DTextureSize = 16384;
Int MaxArrayTextureLayers = 2048;
Int MaxCubeMapTextureSize = 16384;
Int MaxFramebufferWidth = 16384;
Int MaxFramebufferHeight = 16384;
Int MaxFramebufferLayers = 2048;
Int MaxRenderbufferSize = 16384;
Int MaxTextureSize = 16384;
Int MaxColorTextureSamples = 1;
Int MaxDepthTextureSamples = 1;
Int MaxFramebufferSamples = 1;
Int MaxIntegerSamples = 1;
Int MaxSamples = 1;
Int MaxSampleMaskWords = 1;
Int MaxTextureImageUnits = 32;
Int MaxVertexTextureImageUnits = 32;
Int MaxComputeTextureImageUnits = 32;
Int MaxCombinedTextureImageUnits = 192;
Int MaxVertexAttribs = 16;
Int MaxComputeShaderStorageBlocks = 8;
Int MaxCombinedShaderStorageBlocks = 32;
Int MaxComputeUniformBlocks = 12;
Int MaxComputeWorkGroupInvocations = 128;
Int MaxShaderStorageBufferBindings = 8;
Int MaxTextureBufferSize = 65536;
Int MaxUniformBufferBindings = 24;
Int MaxUniformBlockSize = 16384;
Int MaxImageUnits = 8;
Int MaxCombinedImageUniforms = 8;
Int MaxComputeImageUniforms = 8;
Int MaxDrawBuffers = 8;
Int MaxColorAttachments = 8;
Int MaxClipDistances = 8;
Int MaxViewports = 16;
Int MaxViewportWidth = 16384;
Int MaxViewportHeight = 16384;
Float ViewportBoundsRangeMin = 0.0f;
Float ViewportBoundsRangeMax = 0.0f;
Int ViewportSubpixelBits = 0;
}; };
} // namespace MG_External } // namespace MG_External
namespace MG_Util::BackendLoader { namespace MG_Util::BackendLoader {
Bool AcquireGLESFunctions(MG_External::GLESFunctionsTable& funcs, void AcquireGLESFunctions(MG_External::GLESFunctionsTable& funcs,
MG_External::EGL::eglGetProcAddress_PTR procAddress); MG_External::EGL::eglGetProcAddress_PTR procAddress);
Bool AcquireEGLFunctions(MG_External::EGLFunctionsTable& funcs); void AcquireEGLFunctions(MG_External::EGLFunctionsTable& funcs);
Bool FillInGLESCapabilities(MG_External::GLESCapabilities& caps, Bool FillInGLESCapabilities(MG_External::GLESCapabilities& caps,
const MG_External::GLESFunctionsTable& glesFuncs); const MG_External::GLESFunctionsTable& glesFuncs);
} // namespace MG_Util::BackendLoader } // namespace MG_Util::BackendLoader
@@ -18,6 +18,29 @@ namespace MobileGL::MG_Util::BackendLoader {
PFN_vkGetPhysicalDeviceProperties2 vkGetPhysicalDeviceProperties2 = nullptr; PFN_vkGetPhysicalDeviceProperties2 vkGetPhysicalDeviceProperties2 = nullptr;
}; };
Int ResolveMaxRenderbufferSize(const VkPhysicalDeviceLimits& limits) {
return std::min<Int>(static_cast<Int>(limits.maxImageDimension2D),
std::min<Int>(static_cast<Int>(limits.maxFramebufferWidth),
static_cast<Int>(limits.maxFramebufferHeight)));
}
Int MaxSampleCountFromFlags(VkSampleCountFlags flags) {
if (flags & VK_SAMPLE_COUNT_64_BIT) return 64;
if (flags & VK_SAMPLE_COUNT_32_BIT) return 32;
if (flags & VK_SAMPLE_COUNT_16_BIT) return 16;
if (flags & VK_SAMPLE_COUNT_8_BIT) return 8;
if (flags & VK_SAMPLE_COUNT_4_BIT) return 4;
if (flags & VK_SAMPLE_COUNT_2_BIT) return 2;
return 1;
}
Int ResolveConservativeFramebufferSampleLimit(const VkPhysicalDeviceLimits& limits) {
const VkSampleCountFlags commonFlags = limits.framebufferColorSampleCounts &
limits.framebufferDepthSampleCounts &
limits.framebufferStencilSampleCounts;
return MaxSampleCountFromFlags(commonFlags);
}
VulkanDynamicFunctions LoadVulkanDynamicFunctions(VkInstance instance) { VulkanDynamicFunctions LoadVulkanDynamicFunctions(VkInstance instance) {
VulkanDynamicFunctions loaded{}; VulkanDynamicFunctions loaded{};
if (instance == VK_NULL_HANDLE) { if (instance == VK_NULL_HANDLE) {
@@ -104,6 +127,57 @@ namespace MobileGL::MG_Util::BackendLoader {
caps.DeviceName = p.deviceName; caps.DeviceName = p.deviceName;
caps.DriverVersionString = DecodeDriverVersion(p.driverVersion); caps.DriverVersionString = DecodeDriverVersion(p.driverVersion);
caps.UniformBufferOffsetAlignment = static_cast<int>(p.limits.minUniformBufferOffsetAlignment); caps.UniformBufferOffsetAlignment = static_cast<int>(p.limits.minUniformBufferOffsetAlignment);
caps.AliasedLineWidthRangeMin = p.limits.lineWidthRange[0];
caps.AliasedLineWidthRangeMax = p.limits.lineWidthRange[1];
caps.SmoothLineWidthRangeMin = p.limits.lineWidthRange[0];
caps.SmoothLineWidthRangeMax = p.limits.lineWidthRange[1];
caps.SmoothLineWidthGranularity = p.limits.lineWidthGranularity;
caps.PointSizeRangeMin = p.limits.pointSizeRange[0];
caps.PointSizeRangeMax = p.limits.pointSizeRange[1];
caps.PointSizeGranularity = p.limits.pointSizeGranularity;
caps.Max3DTextureSize = static_cast<Int>(p.limits.maxImageDimension3D);
caps.MaxArrayTextureLayers = static_cast<Int>(p.limits.maxImageArrayLayers);
caps.MaxCubeMapTextureSize = static_cast<Int>(p.limits.maxImageDimensionCube);
caps.MaxFramebufferWidth = static_cast<Int>(p.limits.maxFramebufferWidth);
caps.MaxFramebufferHeight = static_cast<Int>(p.limits.maxFramebufferHeight);
caps.MaxFramebufferLayers = static_cast<Int>(p.limits.maxFramebufferLayers);
caps.MaxRenderbufferSize = ResolveMaxRenderbufferSize(p.limits);
caps.MaxTextureSize = static_cast<Int>(p.limits.maxImageDimension2D);
caps.MaxColorTextureSamples = MaxSampleCountFromFlags(p.limits.sampledImageColorSampleCounts);
caps.MaxDepthTextureSamples = MaxSampleCountFromFlags(p.limits.sampledImageDepthSampleCounts);
caps.MaxFramebufferSamples = ResolveConservativeFramebufferSampleLimit(p.limits);
caps.MaxIntegerSamples = MaxSampleCountFromFlags(p.limits.sampledImageIntegerSampleCounts);
caps.MaxSamples = caps.MaxFramebufferSamples;
caps.MaxSampleMaskWords = static_cast<Int>(p.limits.maxSampleMaskWords);
caps.MaxTextureImageUnits = static_cast<Int>(p.limits.maxPerStageDescriptorSampledImages);
caps.MaxVertexTextureImageUnits = static_cast<Int>(p.limits.maxPerStageDescriptorSampledImages);
caps.MaxComputeTextureImageUnits = static_cast<Int>(p.limits.maxPerStageDescriptorSampledImages);
caps.MaxCombinedTextureImageUnits = static_cast<Int>(p.limits.maxDescriptorSetSampledImages);
caps.MaxVertexAttribs = static_cast<Int>(p.limits.maxVertexInputAttributes);
caps.MaxComputeShaderStorageBlocks = static_cast<Int>(p.limits.maxPerStageDescriptorStorageBuffers);
caps.MaxCombinedShaderStorageBlocks = static_cast<Int>(p.limits.maxDescriptorSetStorageBuffers);
caps.MaxComputeUniformBlocks = static_cast<Int>(p.limits.maxPerStageDescriptorUniformBuffers);
caps.MaxComputeWorkGroupInvocations = static_cast<Int>(p.limits.maxComputeWorkGroupInvocations);
caps.MaxShaderStorageBufferBindings = static_cast<Int>(p.limits.maxDescriptorSetStorageBuffers);
caps.MaxTextureBufferSize = static_cast<Int>(p.limits.maxTexelBufferElements);
caps.MaxUniformBufferBindings = static_cast<Int>(p.limits.maxDescriptorSetUniformBuffers);
caps.MaxUniformBlockSize = static_cast<Int>(p.limits.maxUniformBufferRange);
caps.MaxImageUnits = static_cast<Int>(p.limits.maxPerStageDescriptorStorageImages);
caps.MaxCombinedImageUniforms = static_cast<Int>(p.limits.maxDescriptorSetStorageImages);
caps.MaxComputeImageUniforms = static_cast<Int>(p.limits.maxPerStageDescriptorStorageImages);
caps.MaxDrawBuffers = static_cast<Int>(p.limits.maxFragmentOutputAttachments);
caps.MaxColorAttachments = static_cast<Int>(p.limits.maxColorAttachments);
caps.MaxClipDistances = static_cast<Int>(p.limits.maxClipDistances);
caps.MaxViewports = static_cast<Int>(p.limits.maxViewports);
caps.MaxViewportWidth = static_cast<Int>(p.limits.maxViewportDimensions[0]);
caps.MaxViewportHeight = static_cast<Int>(p.limits.maxViewportDimensions[1]);
caps.ViewportBoundsRangeMin = p.limits.viewportBoundsRange[0];
caps.ViewportBoundsRangeMax = p.limits.viewportBoundsRange[1];
caps.ViewportSubpixelBits = static_cast<Int>(p.limits.viewportSubPixelBits);
VkPhysicalDeviceFeatures supportedFeatures{};
vkGetPhysicalDeviceFeatures(physicalDevice, &supportedFeatures);
caps.SupportsWideLines = supportedFeatures.wideLines == VK_TRUE;
caps.MaxShaderStorageBlockSize = static_cast<SizeT>(p.limits.maxStorageBufferRange); caps.MaxShaderStorageBlockSize = static_cast<SizeT>(p.limits.maxStorageBufferRange);
const Bool supportsShaderSubgroup = vk.vkGetPhysicalDeviceProperties2 && const Bool supportsShaderSubgroup = vk.vkGetPhysicalDeviceProperties2 &&
HasUsableShaderSubgroupSupport(subgroupProps); HasUsableShaderSubgroupSupport(subgroupProps);
@@ -137,6 +211,54 @@ namespace MobileGL::MG_Util::BackendLoader {
caps.DeviceName = properties.deviceName; caps.DeviceName = properties.deviceName;
caps.DriverVersionString = DecodeDriverVersion(properties.driverVersion); caps.DriverVersionString = DecodeDriverVersion(properties.driverVersion);
caps.UniformBufferOffsetAlignment = static_cast<int>(properties.limits.minUniformBufferOffsetAlignment); caps.UniformBufferOffsetAlignment = static_cast<int>(properties.limits.minUniformBufferOffsetAlignment);
caps.AliasedLineWidthRangeMin = properties.limits.lineWidthRange[0];
caps.AliasedLineWidthRangeMax = properties.limits.lineWidthRange[1];
caps.SmoothLineWidthRangeMin = properties.limits.lineWidthRange[0];
caps.SmoothLineWidthRangeMax = properties.limits.lineWidthRange[1];
caps.SmoothLineWidthGranularity = properties.limits.lineWidthGranularity;
caps.PointSizeRangeMin = properties.limits.pointSizeRange[0];
caps.PointSizeRangeMax = properties.limits.pointSizeRange[1];
caps.PointSizeGranularity = properties.limits.pointSizeGranularity;
caps.Max3DTextureSize = static_cast<Int>(properties.limits.maxImageDimension3D);
caps.MaxArrayTextureLayers = static_cast<Int>(properties.limits.maxImageArrayLayers);
caps.MaxCubeMapTextureSize = static_cast<Int>(properties.limits.maxImageDimensionCube);
caps.MaxFramebufferWidth = static_cast<Int>(properties.limits.maxFramebufferWidth);
caps.MaxFramebufferHeight = static_cast<Int>(properties.limits.maxFramebufferHeight);
caps.MaxFramebufferLayers = static_cast<Int>(properties.limits.maxFramebufferLayers);
caps.MaxRenderbufferSize = ResolveMaxRenderbufferSize(properties.limits);
caps.MaxTextureSize = static_cast<Int>(properties.limits.maxImageDimension2D);
caps.MaxColorTextureSamples = MaxSampleCountFromFlags(properties.limits.sampledImageColorSampleCounts);
caps.MaxDepthTextureSamples = MaxSampleCountFromFlags(properties.limits.sampledImageDepthSampleCounts);
caps.MaxFramebufferSamples = ResolveConservativeFramebufferSampleLimit(properties.limits);
caps.MaxIntegerSamples = MaxSampleCountFromFlags(properties.limits.sampledImageIntegerSampleCounts);
caps.MaxSamples = caps.MaxFramebufferSamples;
caps.MaxSampleMaskWords = static_cast<Int>(properties.limits.maxSampleMaskWords);
caps.MaxTextureImageUnits = static_cast<Int>(properties.limits.maxPerStageDescriptorSampledImages);
caps.MaxVertexTextureImageUnits = static_cast<Int>(properties.limits.maxPerStageDescriptorSampledImages);
caps.MaxComputeTextureImageUnits = static_cast<Int>(properties.limits.maxPerStageDescriptorSampledImages);
caps.MaxCombinedTextureImageUnits = static_cast<Int>(properties.limits.maxDescriptorSetSampledImages);
caps.MaxVertexAttribs = static_cast<Int>(properties.limits.maxVertexInputAttributes);
caps.MaxComputeShaderStorageBlocks = static_cast<Int>(properties.limits.maxPerStageDescriptorStorageBuffers);
caps.MaxCombinedShaderStorageBlocks = static_cast<Int>(properties.limits.maxDescriptorSetStorageBuffers);
caps.MaxComputeUniformBlocks = static_cast<Int>(properties.limits.maxPerStageDescriptorUniformBuffers);
caps.MaxComputeWorkGroupInvocations = static_cast<Int>(properties.limits.maxComputeWorkGroupInvocations);
caps.MaxShaderStorageBufferBindings = static_cast<Int>(properties.limits.maxDescriptorSetStorageBuffers);
caps.MaxTextureBufferSize = static_cast<Int>(properties.limits.maxTexelBufferElements);
caps.MaxUniformBufferBindings = static_cast<Int>(properties.limits.maxDescriptorSetUniformBuffers);
caps.MaxUniformBlockSize = static_cast<Int>(properties.limits.maxUniformBufferRange);
caps.MaxImageUnits = static_cast<Int>(properties.limits.maxPerStageDescriptorStorageImages);
caps.MaxCombinedImageUniforms = static_cast<Int>(properties.limits.maxDescriptorSetStorageImages);
caps.MaxComputeImageUniforms = static_cast<Int>(properties.limits.maxPerStageDescriptorStorageImages);
caps.MaxDrawBuffers = static_cast<Int>(properties.limits.maxFragmentOutputAttachments);
caps.MaxColorAttachments = static_cast<Int>(properties.limits.maxColorAttachments);
caps.MaxClipDistances = static_cast<Int>(properties.limits.maxClipDistances);
caps.MaxViewports = static_cast<Int>(properties.limits.maxViewports);
caps.MaxViewportWidth = static_cast<Int>(properties.limits.maxViewportDimensions[0]);
caps.MaxViewportHeight = static_cast<Int>(properties.limits.maxViewportDimensions[1]);
caps.ViewportBoundsRangeMin = properties.limits.viewportBoundsRange[0];
caps.ViewportBoundsRangeMax = properties.limits.viewportBoundsRange[1];
caps.ViewportSubpixelBits = static_cast<Int>(properties.limits.viewportSubPixelBits);
caps.SupportsWideLines = false;
caps.MaxShaderStorageBlockSize = static_cast<SizeT>(properties.limits.maxStorageBufferRange); caps.MaxShaderStorageBlockSize = static_cast<SizeT>(properties.limits.maxStorageBufferRange);
caps.SupportsShaderSubgroup = false; caps.SupportsShaderSubgroup = false;
caps.SubgroupSize = 0; caps.SubgroupSize = 0;
@@ -16,6 +16,54 @@ namespace MobileGL {
String DeviceName; String DeviceName;
String DriverVersionString; String DriverVersionString;
Int UniformBufferOffsetAlignment = 256; Int UniformBufferOffsetAlignment = 256;
Float AliasedLineWidthRangeMin = 1.0f;
Float AliasedLineWidthRangeMax = 1.0f;
Float SmoothLineWidthRangeMin = 1.0f;
Float SmoothLineWidthRangeMax = 1.0f;
Float SmoothLineWidthGranularity = 1.0f;
Float PointSizeRangeMin = 1.0f;
Float PointSizeRangeMax = 1.0f;
Float PointSizeGranularity = 1.0f;
Int Max3DTextureSize = 16384;
Int MaxArrayTextureLayers = 2048;
Int MaxCubeMapTextureSize = 16384;
Int MaxFramebufferWidth = 16384;
Int MaxFramebufferHeight = 16384;
Int MaxFramebufferLayers = 2048;
Int MaxRenderbufferSize = 16384;
Int MaxTextureSize = 16384;
Int MaxColorTextureSamples = 1;
Int MaxDepthTextureSamples = 1;
Int MaxFramebufferSamples = 1;
Int MaxIntegerSamples = 1;
Int MaxSamples = 1;
Int MaxSampleMaskWords = 1;
Int MaxTextureImageUnits = 32;
Int MaxVertexTextureImageUnits = 32;
Int MaxComputeTextureImageUnits = 32;
Int MaxCombinedTextureImageUnits = 192;
Int MaxVertexAttribs = 16;
Int MaxComputeShaderStorageBlocks = 8;
Int MaxCombinedShaderStorageBlocks = 32;
Int MaxComputeUniformBlocks = 12;
Int MaxComputeWorkGroupInvocations = 128;
Int MaxShaderStorageBufferBindings = 8;
Int MaxTextureBufferSize = 65536;
Int MaxUniformBufferBindings = 24;
Int MaxUniformBlockSize = 16384;
Int MaxImageUnits = 8;
Int MaxCombinedImageUniforms = 8;
Int MaxComputeImageUniforms = 8;
Int MaxDrawBuffers = 8;
Int MaxColorAttachments = 8;
Int MaxClipDistances = 8;
Int MaxViewports = 16;
Int MaxViewportWidth = 16384;
Int MaxViewportHeight = 16384;
Float ViewportBoundsRangeMin = 0.0f;
Float ViewportBoundsRangeMax = 0.0f;
Int ViewportSubpixelBits = 0;
Bool SupportsWideLines = false;
SizeT MaxShaderStorageBlockSize = 128 * 1024 * 1024; SizeT MaxShaderStorageBlockSize = 128 * 1024 * 1024;
Bool SupportsShaderSubgroup = false; Bool SupportsShaderSubgroup = false;
Uint32 SubgroupSize = 0; Uint32 SubgroupSize = 0;
@@ -24,6 +24,8 @@ namespace MobileGL {
return DataType::Int32; return DataType::Int32;
case GL_UNSIGNED_INT: case GL_UNSIGNED_INT:
return DataType::Uint32; return DataType::Uint32;
case GL_FIXED:
return DataType::Fixed32;
case GL_HALF_FLOAT: case GL_HALF_FLOAT:
return DataType::Float16; return DataType::Float16;
case GL_FLOAT: case GL_FLOAT:
@@ -36,10 +36,12 @@ namespace MobileGL {
return FramebufferAttachmentType::Depth; return FramebufferAttachmentType::Depth;
case GL_STENCIL_ATTACHMENT: case GL_STENCIL_ATTACHMENT:
return FramebufferAttachmentType::Stencil; return FramebufferAttachmentType::Stencil;
case GL_FRONT:
case GL_FRONT_LEFT: case GL_FRONT_LEFT:
return FramebufferAttachmentType::FrontLeft; return FramebufferAttachmentType::FrontLeft;
case GL_FRONT_RIGHT: case GL_FRONT_RIGHT:
return FramebufferAttachmentType::FrontRight; return FramebufferAttachmentType::FrontRight;
case GL_BACK:
case GL_BACK_LEFT: case GL_BACK_LEFT:
return FramebufferAttachmentType::BackLeft; return FramebufferAttachmentType::BackLeft;
case GL_BACK_RIGHT: case GL_BACK_RIGHT:
@@ -62,6 +62,45 @@ namespace MobileGL {
} }
} }
LogicOperation ConvertGLEnumToLogicOperation(GLenum v) {
switch (v) {
case GL_CLEAR:
return LogicOperation::Clear;
case GL_AND:
return LogicOperation::And;
case GL_AND_REVERSE:
return LogicOperation::AndReverse;
case GL_COPY:
return LogicOperation::Copy;
case GL_AND_INVERTED:
return LogicOperation::AndInverted;
case GL_NOOP:
return LogicOperation::Noop;
case GL_XOR:
return LogicOperation::Xor;
case GL_OR:
return LogicOperation::Or;
case GL_NOR:
return LogicOperation::Nor;
case GL_EQUIV:
return LogicOperation::Equiv;
case GL_INVERT:
return LogicOperation::Invert;
case GL_OR_REVERSE:
return LogicOperation::OrReverse;
case GL_COPY_INVERTED:
return LogicOperation::CopyInverted;
case GL_OR_INVERTED:
return LogicOperation::OrInverted;
case GL_NAND:
return LogicOperation::Nand;
case GL_SET:
return LogicOperation::Set;
default:
return LogicOperation::Unknown;
}
}
DepthTestFunc ConvertGLEnumToDepthTestFunc(GLenum v) { DepthTestFunc ConvertGLEnumToDepthTestFunc(GLenum v) {
switch (v) { switch (v) {
case GL_NEVER: case GL_NEVER:
@@ -85,6 +124,29 @@ namespace MobileGL {
} }
} }
StencilOperation ConvertGLEnumToStencilOperation(GLenum v) {
switch (v) {
case GL_KEEP:
return StencilOperation::Keep;
case GL_ZERO:
return StencilOperation::Zero;
case GL_REPLACE:
return StencilOperation::Replace;
case GL_INCR:
return StencilOperation::IncrementClamp;
case GL_DECR:
return StencilOperation::DecrementClamp;
case GL_INVERT:
return StencilOperation::Invert;
case GL_INCR_WRAP:
return StencilOperation::IncrementWrap;
case GL_DECR_WRAP:
return StencilOperation::DecrementWrap;
default:
return StencilOperation::Unknown;
}
}
PixelStoreParam ConvertGLEnumToPixelStoreParam(GLenum v) { PixelStoreParam ConvertGLEnumToPixelStoreParam(GLenum v) {
switch (v) { switch (v) {
case GL_PACK_ALIGNMENT: case GL_PACK_ALIGNMENT:
@@ -14,7 +14,9 @@ namespace MobileGL {
namespace MG_Util { namespace MG_Util {
BlendFactor ConvertGLEnumToBlendFactor(GLenum value); BlendFactor ConvertGLEnumToBlendFactor(GLenum value);
BlendEquation ConvertGLEnumToBlendEquation(GLenum value); BlendEquation ConvertGLEnumToBlendEquation(GLenum value);
LogicOperation ConvertGLEnumToLogicOperation(GLenum value);
DepthTestFunc ConvertGLEnumToDepthTestFunc(GLenum value); DepthTestFunc ConvertGLEnumToDepthTestFunc(GLenum value);
StencilOperation ConvertGLEnumToStencilOperation(GLenum value);
PixelStoreParam ConvertGLEnumToPixelStoreParam(GLenum value); PixelStoreParam ConvertGLEnumToPixelStoreParam(GLenum value);
CullFaceMode ConvertGLEnumToCullFaceMode(GLenum value); CullFaceMode ConvertGLEnumToCullFaceMode(GLenum value);
FrontFaceMode ConvertGLEnumToFrontFaceMode(GLenum value); FrontFaceMode ConvertGLEnumToFrontFaceMode(GLenum value);
@@ -14,12 +14,16 @@ namespace MobileGL {
TextureTarget ConvertGLEnumToTextureTarget(GLenum target) { TextureTarget ConvertGLEnumToTextureTarget(GLenum target) {
switch (target) { switch (target) {
case GL_TEXTURE_1D: case GL_TEXTURE_1D:
case GL_PROXY_TEXTURE_1D:
return TextureTarget::Texture1D; return TextureTarget::Texture1D;
case GL_TEXTURE_2D: case GL_TEXTURE_2D:
case GL_PROXY_TEXTURE_2D:
return TextureTarget::Texture2D; return TextureTarget::Texture2D;
case GL_TEXTURE_3D: case GL_TEXTURE_3D:
case GL_PROXY_TEXTURE_3D:
return TextureTarget::Texture3D; return TextureTarget::Texture3D;
case GL_TEXTURE_CUBE_MAP: case GL_TEXTURE_CUBE_MAP:
case GL_PROXY_TEXTURE_CUBE_MAP:
case GL_TEXTURE_CUBE_MAP_POSITIVE_X: case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
@@ -28,18 +32,24 @@ namespace MobileGL {
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
return TextureTarget::TextureCubeMap; return TextureTarget::TextureCubeMap;
case GL_TEXTURE_2D_ARRAY: case GL_TEXTURE_2D_ARRAY:
case GL_PROXY_TEXTURE_2D_ARRAY:
return TextureTarget::Texture2DArray; return TextureTarget::Texture2DArray;
case GL_TEXTURE_2D_MULTISAMPLE: case GL_TEXTURE_2D_MULTISAMPLE:
case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
return TextureTarget::Texture2DMultisample; return TextureTarget::Texture2DMultisample;
case GL_TEXTURE_CUBE_MAP_ARRAY: case GL_TEXTURE_CUBE_MAP_ARRAY:
case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
return TextureTarget::TextureCubeMapArray; return TextureTarget::TextureCubeMapArray;
case GL_TEXTURE_BUFFER: case GL_TEXTURE_BUFFER:
return TextureTarget::TextureBuffer; return TextureTarget::TextureBuffer;
case GL_TEXTURE_1D_ARRAY: case GL_TEXTURE_1D_ARRAY:
case GL_PROXY_TEXTURE_1D_ARRAY:
return TextureTarget::Texture1DArray; return TextureTarget::Texture1DArray;
case GL_TEXTURE_RECTANGLE: case GL_TEXTURE_RECTANGLE:
case GL_PROXY_TEXTURE_RECTANGLE:
return TextureTarget::TextureRectangle; return TextureTarget::TextureRectangle;
case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
return TextureTarget::Texture2DMultisampleArray; return TextureTarget::Texture2DMultisampleArray;
default: default:
return TextureTarget::Unknown; return TextureTarget::Unknown;
@@ -24,6 +24,8 @@ namespace MobileGL {
return GL_INT; return GL_INT;
case DataType::Uint32: case DataType::Uint32:
return GL_UNSIGNED_INT; return GL_UNSIGNED_INT;
case DataType::Fixed32:
return GL_FIXED;
case DataType::Float16: case DataType::Float16:
return GL_HALF_FLOAT; return GL_HALF_FLOAT;
case DataType::Float32: case DataType::Float32:
@@ -16,8 +16,9 @@ namespace MobileGL {
return GL_DRAW_FRAMEBUFFER; return GL_DRAW_FRAMEBUFFER;
case FramebufferTarget::Read: case FramebufferTarget::Read:
return GL_READ_FRAMEBUFFER; return GL_READ_FRAMEBUFFER;
case FramebufferTarget::Unknown:
default: default:
return GL_DRAW_FRAMEBUFFER; return GL_UNKNOWN_MGL;
} }
} }
@@ -29,6 +30,8 @@ namespace MobileGL {
} }
switch (type) { switch (type) {
case FramebufferAttachmentType::None:
return GL_NONE;
case FramebufferAttachmentType::Depth: case FramebufferAttachmentType::Depth:
return GL_DEPTH_ATTACHMENT; return GL_DEPTH_ATTACHMENT;
case FramebufferAttachmentType::Stencil: case FramebufferAttachmentType::Stencil:
@@ -41,8 +44,9 @@ namespace MobileGL {
return GL_BACK_LEFT; return GL_BACK_LEFT;
case FramebufferAttachmentType::BackRight: case FramebufferAttachmentType::BackRight:
return GL_BACK_RIGHT; return GL_BACK_RIGHT;
case FramebufferAttachmentType::Unknown:
default: default:
return GL_NONE; return GL_UNKNOWN_MGL;
} }
} }
@@ -50,8 +54,9 @@ namespace MobileGL {
switch (target) { switch (target) {
case RenderbufferTarget::Renderbuffer: case RenderbufferTarget::Renderbuffer:
return GL_RENDERBUFFER; return GL_RENDERBUFFER;
case RenderbufferTarget::Unknown:
default: default:
return GL_RENDERBUFFER; return GL_UNKNOWN_MGL;
} }
} }
@@ -63,6 +63,45 @@ namespace MobileGL {
} }
} }
GLenum ConvertLogicOperationToGLEnum(LogicOperation v) {
switch (v) {
case LogicOperation::Clear:
return GL_CLEAR;
case LogicOperation::And:
return GL_AND;
case LogicOperation::AndReverse:
return GL_AND_REVERSE;
case LogicOperation::Copy:
return GL_COPY;
case LogicOperation::AndInverted:
return GL_AND_INVERTED;
case LogicOperation::Noop:
return GL_NOOP;
case LogicOperation::Xor:
return GL_XOR;
case LogicOperation::Or:
return GL_OR;
case LogicOperation::Nor:
return GL_NOR;
case LogicOperation::Equiv:
return GL_EQUIV;
case LogicOperation::Invert:
return GL_INVERT;
case LogicOperation::OrReverse:
return GL_OR_REVERSE;
case LogicOperation::CopyInverted:
return GL_COPY_INVERTED;
case LogicOperation::OrInverted:
return GL_OR_INVERTED;
case LogicOperation::Nand:
return GL_NAND;
case LogicOperation::Set:
return GL_SET;
default:
return GL_UNKNOWN_MGL;
}
}
GLenum ConvertDepthTestFuncToGLEnum(DepthTestFunc v) { GLenum ConvertDepthTestFuncToGLEnum(DepthTestFunc v) {
switch (v) { switch (v) {
case DepthTestFunc::Never: case DepthTestFunc::Never:
@@ -86,6 +125,29 @@ namespace MobileGL {
} }
} }
GLenum ConvertStencilOperationToGLEnum(StencilOperation v) {
switch (v) {
case StencilOperation::Keep:
return GL_KEEP;
case StencilOperation::Zero:
return GL_ZERO;
case StencilOperation::Replace:
return GL_REPLACE;
case StencilOperation::IncrementClamp:
return GL_INCR;
case StencilOperation::DecrementClamp:
return GL_DECR;
case StencilOperation::Invert:
return GL_INVERT;
case StencilOperation::IncrementWrap:
return GL_INCR_WRAP;
case StencilOperation::DecrementWrap:
return GL_DECR_WRAP;
default:
return GL_UNKNOWN_MGL;
}
}
GLenum ConvertPixelStoreParamToGLEnum(PixelStoreParam v) { GLenum ConvertPixelStoreParamToGLEnum(PixelStoreParam v) {
switch (v) { switch (v) {
case PixelStoreParam::PackAlignment: case PixelStoreParam::PackAlignment:
@@ -14,7 +14,9 @@ namespace MobileGL {
namespace MG_Util { namespace MG_Util {
GLenum ConvertBlendFactorToGLEnum(BlendFactor value); GLenum ConvertBlendFactorToGLEnum(BlendFactor value);
GLenum ConvertBlendEquationToGLEnum(BlendEquation value); GLenum ConvertBlendEquationToGLEnum(BlendEquation value);
GLenum ConvertLogicOperationToGLEnum(LogicOperation value);
GLenum ConvertDepthTestFuncToGLEnum(DepthTestFunc value); GLenum ConvertDepthTestFuncToGLEnum(DepthTestFunc value);
GLenum ConvertStencilOperationToGLEnum(StencilOperation value);
GLenum ConvertPixelStoreParamToGLEnum(PixelStoreParam value); GLenum ConvertPixelStoreParamToGLEnum(PixelStoreParam value);
GLenum ConvertCullFaceModeToGLEnum(CullFaceMode value); GLenum ConvertCullFaceModeToGLEnum(CullFaceMode value);
GLenum ConvertFrontFaceModeToGLEnum(FrontFaceMode value); GLenum ConvertFrontFaceModeToGLEnum(FrontFaceMode value);
@@ -110,6 +110,8 @@ namespace MobileGL {
return GL_RGB10; return GL_RGB10;
case TextureInternalFormat::RGB12: case TextureInternalFormat::RGB12:
return GL_RGB12; return GL_RGB12;
case TextureInternalFormat::RGB16:
return GL_RGB16;
case TextureInternalFormat::RGB16Snorm: case TextureInternalFormat::RGB16Snorm:
return GL_RGB16_SNORM; return GL_RGB16_SNORM;
case TextureInternalFormat::RGBA2: case TextureInternalFormat::RGBA2:
@@ -267,6 +269,8 @@ namespace MobileGL {
return GL_UNSIGNED_SHORT_5_5_5_1; return GL_UNSIGNED_SHORT_5_5_5_1;
case TexturePixelDataType::UnsignedShort1555Rev: case TexturePixelDataType::UnsignedShort1555Rev:
return GL_UNSIGNED_SHORT_1_5_5_5_REV; return GL_UNSIGNED_SHORT_1_5_5_5_REV;
case TexturePixelDataType::UnsignedInt8888:
return GL_UNSIGNED_INT_8_8_8_8;
case TexturePixelDataType::UnsignedInt8888Rev: case TexturePixelDataType::UnsignedInt8888Rev:
return GL_UNSIGNED_INT_8_8_8_8_REV; return GL_UNSIGNED_INT_8_8_8_8_REV;
case TexturePixelDataType::UnsignedInt1010102: case TexturePixelDataType::UnsignedInt1010102:
@@ -74,6 +74,10 @@ namespace MobileGL {
} }
String ConvertBufferMappingAccessToString(Flags<BufferMappingAccessBit> access) { String ConvertBufferMappingAccessToString(Flags<BufferMappingAccessBit> access) {
if (access == BufferMappingAccessBit::Null) {
return "[]";
}
String result = "["; String result = "[";
if (access & BufferMappingAccessBit::Read) result += "Read, "; if (access & BufferMappingAccessBit::Read) result += "Read, ";
if (access & BufferMappingAccessBit::Write) result += "Write, "; if (access & BufferMappingAccessBit::Write) result += "Write, ";
@@ -86,7 +90,7 @@ namespace MobileGL {
result.pop_back(); result.pop_back();
result.pop_back(); result.pop_back();
result += "]"; result += "]";
return result.empty() ? "[]" : result; return result;
} }
} // namespace MG_Util } // namespace MG_Util
} // namespace MobileGL } // namespace MobileGL
@@ -29,6 +29,16 @@ namespace MobileGL {
} }
switch (attachment) { switch (attachment) {
case FramebufferAttachmentType::None:
return "None";
case FramebufferAttachmentType::FrontLeft:
return "FrontLeft";
case FramebufferAttachmentType::FrontRight:
return "FrontRight";
case FramebufferAttachmentType::BackLeft:
return "BackLeft";
case FramebufferAttachmentType::BackRight:
return "BackRight";
case FramebufferAttachmentType::Depth: case FramebufferAttachmentType::Depth:
return "Depth"; return "Depth";
case FramebufferAttachmentType::Stencil: case FramebufferAttachmentType::Stencil:
@@ -45,6 +45,45 @@ namespace MobileGL {
} }
} }
String ConvertLogicOperationToString(LogicOperation v) {
switch (v) {
case LogicOperation::Clear:
return "Clear";
case LogicOperation::And:
return "And";
case LogicOperation::AndReverse:
return "AndReverse";
case LogicOperation::Copy:
return "Copy";
case LogicOperation::AndInverted:
return "AndInverted";
case LogicOperation::Noop:
return "Noop";
case LogicOperation::Xor:
return "Xor";
case LogicOperation::Or:
return "Or";
case LogicOperation::Nor:
return "Nor";
case LogicOperation::Equiv:
return "Equiv";
case LogicOperation::Invert:
return "Invert";
case LogicOperation::OrReverse:
return "OrReverse";
case LogicOperation::CopyInverted:
return "CopyInverted";
case LogicOperation::OrInverted:
return "OrInverted";
case LogicOperation::Nand:
return "Nand";
case LogicOperation::Set:
return "Set";
default:
return "Unknown";
}
}
String ConvertDepthTestFuncToString(DepthTestFunc v) { String ConvertDepthTestFuncToString(DepthTestFunc v) {
switch (v) { switch (v) {
case DepthTestFunc::Never: case DepthTestFunc::Never:
@@ -68,6 +107,29 @@ namespace MobileGL {
} }
} }
String ConvertStencilOperationToString(StencilOperation v) {
switch (v) {
case StencilOperation::Keep:
return "Keep";
case StencilOperation::Zero:
return "Zero";
case StencilOperation::Replace:
return "Replace";
case StencilOperation::IncrementClamp:
return "IncrementClamp";
case StencilOperation::DecrementClamp:
return "DecrementClamp";
case StencilOperation::Invert:
return "Invert";
case StencilOperation::IncrementWrap:
return "IncrementWrap";
case StencilOperation::DecrementWrap:
return "DecrementWrap";
default:
return "Unknown";
}
}
String ConvertPixelStoreParamToString(PixelStoreParam v) { String ConvertPixelStoreParamToString(PixelStoreParam v) {
switch (v) { switch (v) {
case PixelStoreParam::PackAlignment: case PixelStoreParam::PackAlignment:
@@ -13,7 +13,9 @@
namespace MobileGL { namespace MobileGL {
namespace MG_Util { namespace MG_Util {
String ConvertBlendFactorToString(BlendFactor value); String ConvertBlendFactorToString(BlendFactor value);
String ConvertLogicOperationToString(LogicOperation value);
String ConvertDepthTestFuncToString(DepthTestFunc value); String ConvertDepthTestFuncToString(DepthTestFunc value);
String ConvertStencilOperationToString(StencilOperation value);
String ConvertPixelStoreParamToString(PixelStoreParam value); String ConvertPixelStoreParamToString(PixelStoreParam value);
String ConvertCullFaceModeToString(CullFaceMode value); String ConvertCullFaceModeToString(CullFaceMode value);
String ConvertFrontFaceModeToString(FrontFaceMode value); String ConvertFrontFaceModeToString(FrontFaceMode value);
@@ -110,6 +110,8 @@ namespace MobileGL {
return "RGB10"; return "RGB10";
case TextureInternalFormat::RGB12: case TextureInternalFormat::RGB12:
return "RGB12"; return "RGB12";
case TextureInternalFormat::RGB16:
return "RGB16";
case TextureInternalFormat::RGB16Snorm: case TextureInternalFormat::RGB16Snorm:
return "RGB16Snorm"; return "RGB16Snorm";
case TextureInternalFormat::RGBA2: case TextureInternalFormat::RGBA2:
@@ -47,6 +47,45 @@ namespace MobileGL {
} }
} }
VkLogicOp ConvertLogicOperationToVkEnum(LogicOperation v) {
switch (v) {
case LogicOperation::Clear:
return VK_LOGIC_OP_CLEAR;
case LogicOperation::And:
return VK_LOGIC_OP_AND;
case LogicOperation::AndReverse:
return VK_LOGIC_OP_AND_REVERSE;
case LogicOperation::Copy:
return VK_LOGIC_OP_COPY;
case LogicOperation::AndInverted:
return VK_LOGIC_OP_AND_INVERTED;
case LogicOperation::Noop:
return VK_LOGIC_OP_NO_OP;
case LogicOperation::Xor:
return VK_LOGIC_OP_XOR;
case LogicOperation::Or:
return VK_LOGIC_OP_OR;
case LogicOperation::Nor:
return VK_LOGIC_OP_NOR;
case LogicOperation::Equiv:
return VK_LOGIC_OP_EQUIVALENT;
case LogicOperation::Invert:
return VK_LOGIC_OP_INVERT;
case LogicOperation::OrReverse:
return VK_LOGIC_OP_OR_REVERSE;
case LogicOperation::CopyInverted:
return VK_LOGIC_OP_COPY_INVERTED;
case LogicOperation::OrInverted:
return VK_LOGIC_OP_OR_INVERTED;
case LogicOperation::Nand:
return VK_LOGIC_OP_NAND;
case LogicOperation::Set:
return VK_LOGIC_OP_SET;
default:
return VK_LOGIC_OP_COPY;
}
}
VkCompareOp ConvertDepthTestFuncToVkEnum(DepthTestFunc v) { VkCompareOp ConvertDepthTestFuncToVkEnum(DepthTestFunc v) {
switch (v) { switch (v) {
case DepthTestFunc::Never: case DepthTestFunc::Never:
@@ -69,6 +108,29 @@ namespace MobileGL {
} }
} }
VkStencilOp ConvertStencilOperationToVkEnum(StencilOperation v) {
switch (v) {
case StencilOperation::Keep:
return VK_STENCIL_OP_KEEP;
case StencilOperation::Zero:
return VK_STENCIL_OP_ZERO;
case StencilOperation::Replace:
return VK_STENCIL_OP_REPLACE;
case StencilOperation::IncrementClamp:
return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
case StencilOperation::DecrementClamp:
return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
case StencilOperation::Invert:
return VK_STENCIL_OP_INVERT;
case StencilOperation::IncrementWrap:
return VK_STENCIL_OP_INCREMENT_AND_WRAP;
case StencilOperation::DecrementWrap:
return VK_STENCIL_OP_DECREMENT_AND_WRAP;
default:
return VK_STENCIL_OP_KEEP;
}
}
VkBlendFactor ConvertBlendFactorToVkEnum(BlendFactor v) { VkBlendFactor ConvertBlendFactorToVkEnum(BlendFactor v) {
switch (v) { switch (v) {
case BlendFactor::Zero: case BlendFactor::Zero:
@@ -14,7 +14,9 @@ namespace MobileGL {
namespace MG_Util { namespace MG_Util {
VkPrimitiveTopology ConvertPrimitiveModeToVkEnum(GLenum mode); VkPrimitiveTopology ConvertPrimitiveModeToVkEnum(GLenum mode);
VkCullModeFlags ConvertCullFaceModeToVkEnum(CullFaceMode value, Bool invertClockwise = false); VkCullModeFlags ConvertCullFaceModeToVkEnum(CullFaceMode value, Bool invertClockwise = false);
VkLogicOp ConvertLogicOperationToVkEnum(LogicOperation value);
VkCompareOp ConvertDepthTestFuncToVkEnum(DepthTestFunc value); VkCompareOp ConvertDepthTestFuncToVkEnum(DepthTestFunc value);
VkStencilOp ConvertStencilOperationToVkEnum(StencilOperation value);
VkBlendFactor ConvertBlendFactorToVkEnum(BlendFactor value); VkBlendFactor ConvertBlendFactorToVkEnum(BlendFactor value);
VkBlendOp ConvertBlendEquationToVkEnum(BlendEquation value); VkBlendOp ConvertBlendEquationToVkEnum(BlendEquation value);
} // namespace MG_Util } // namespace MG_Util
+3 -1
View File
@@ -95,11 +95,13 @@ namespace MobileGL {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
int n = std::vsnprintf(buffer, sizeof(buffer), fmt, args); int n = std::vsnprintf(buffer, sizeof(buffer), fmt, args);
const SizeT messageLength =
(n < 0) ? 0 : std::min(static_cast<SizeT>(n), sizeof(buffer) - static_cast<SizeT>(1));
std::string out = header + std::string out = header +
#if MOBILEGL_LOG_ENABLE_STACKTRACE #if MOBILEGL_LOG_ENABLE_STACKTRACE
padding + padding +
#endif #endif
std::string(buffer, n) + "\n"; std::string(buffer, messageLength) + "\n";
#if MOBILEGL_LOG_ENABLE_CONSOLE #if MOBILEGL_LOG_ENABLE_CONSOLE
std::fwrite(out.c_str(), 1, out.size(), stdout); std::fwrite(out.c_str(), 1, out.size(), stdout);
+25 -2
View File
@@ -43,6 +43,10 @@ namespace MobileGL {
case TextureInternalFormat::DepthComponent24: case TextureInternalFormat::DepthComponent24:
return 3; return 3;
case TextureInternalFormat::RGB10:
case TextureInternalFormat::RGB12:
case TextureInternalFormat::RGB16:
case TextureInternalFormat::RGB16Snorm:
case TextureInternalFormat::RGBA2: case TextureInternalFormat::RGBA2:
case TextureInternalFormat::RGBA4: case TextureInternalFormat::RGBA4:
case TextureInternalFormat::RGB5A1: case TextureInternalFormat::RGB5A1:
@@ -54,6 +58,8 @@ namespace MobileGL {
case TextureInternalFormat::RGB10A2: case TextureInternalFormat::RGB10A2:
case TextureInternalFormat::RGB10A2UI: case TextureInternalFormat::RGB10A2UI:
case TextureInternalFormat::R32F: case TextureInternalFormat::R32F:
case TextureInternalFormat::R32I:
case TextureInternalFormat::R32UI:
case TextureInternalFormat::DepthComponent: case TextureInternalFormat::DepthComponent:
case TextureInternalFormat::DepthComponent32: case TextureInternalFormat::DepthComponent32:
case TextureInternalFormat::DepthComponent32F: case TextureInternalFormat::DepthComponent32F:
@@ -179,6 +185,7 @@ namespace MobileGL {
case TextureInternalFormat::RGB10: case TextureInternalFormat::RGB10:
case TextureInternalFormat::RGB12: case TextureInternalFormat::RGB12:
case TextureInternalFormat::RGB16: case TextureInternalFormat::RGB16:
case TextureInternalFormat::RGB16Snorm:
case TextureInternalFormat::SRGB8: case TextureInternalFormat::SRGB8:
case TextureInternalFormat::RGB8I: case TextureInternalFormat::RGB8I:
case TextureInternalFormat::RGB8UI: case TextureInternalFormat::RGB8UI:
@@ -236,7 +243,6 @@ namespace MobileGL {
case TexturePixelDataType::UnsignedInt248: case TexturePixelDataType::UnsignedInt248:
case TexturePixelDataType::Float32UnsignedInt248Rev: case TexturePixelDataType::Float32UnsignedInt248Rev:
return 4; return 4;
return 4;
default: default:
return 0; return 0;
} }
@@ -339,6 +345,22 @@ namespace MobileGL {
s.Green = 8; s.Green = 8;
s.Blue = 8; s.Blue = 8;
break; break;
case TextureInternalFormat::RGB10:
s.Red = 10;
s.Green = 10;
s.Blue = 10;
break;
case TextureInternalFormat::RGB12:
s.Red = 12;
s.Green = 12;
s.Blue = 12;
break;
case TextureInternalFormat::RGB16:
case TextureInternalFormat::RGB16Snorm:
s.Red = 16;
s.Green = 16;
s.Blue = 16;
break;
case TextureInternalFormat::R3G3B2: case TextureInternalFormat::R3G3B2:
s.Red = 3; s.Red = 3;
@@ -370,7 +392,6 @@ namespace MobileGL {
case TextureInternalFormat::RGBA8UI: case TextureInternalFormat::RGBA8UI:
case TextureInternalFormat::SRGB8Alpha8: case TextureInternalFormat::SRGB8Alpha8:
case TextureInternalFormat::RGBA: case TextureInternalFormat::RGBA:
break;
s.Red = 8; s.Red = 8;
s.Green = 8; s.Green = 8;
s.Blue = 8; s.Blue = 8;
@@ -385,6 +406,8 @@ namespace MobileGL {
break; break;
case TextureInternalFormat::R32F: case TextureInternalFormat::R32F:
case TextureInternalFormat::R32I:
case TextureInternalFormat::R32UI:
s.Red = 32; s.Red = 32;
break; break;
case TextureInternalFormat::RG32F: case TextureInternalFormat::RG32F:
@@ -314,6 +314,10 @@ namespace MobileGL {
size_t commentStartPos = source.find("/*"); size_t commentStartPos = source.find("/*");
while (commentStartPos != String::npos) { while (commentStartPos != String::npos) {
size_t commentEndPos = source.find("*/", commentStartPos); size_t commentEndPos = source.find("*/", commentStartPos);
if (commentEndPos == String::npos) {
source.erase(commentStartPos);
break;
}
// + length of "*/" // + length of "*/"
source = source.replace(commentStartPos, commentEndPos - commentStartPos + 2, ""); source = source.replace(commentStartPos, commentEndPos - commentStartPos + 2, "");
commentStartPos = source.find("/*", commentStartPos); commentStartPos = source.find("/*", commentStartPos);
@@ -120,11 +120,27 @@ 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 = spv::Op replacementOp = spv::Op::OpNop;
(inst.opcode() == spv::Op::OpFOrdEqual || inst.opcode() == spv::Op::OpFUnordEqual); switch (inst.opcode()) {
case spv::Op::OpFOrdEqual:
replacementOp = spv::Op::OpFOrdLessThan;
break;
case spv::Op::OpFUnordEqual:
replacementOp = spv::Op::OpFUnordLessThan;
break;
case spv::Op::OpFOrdNotEqual:
replacementOp = spv::Op::OpFOrdGreaterThanEqual;
break;
case spv::Op::OpFUnordNotEqual:
replacementOp = spv::Op::OpFUnordGreaterThanEqual;
break;
default:
MOBILEGL_ASSERT(false, "Unexpected float compare opcode: %d",
static_cast<int>(inst.opcode()));
break;
}
Instruction* less_than_inst = builder.AddInstruction(MakeUnique<Instruction>( Instruction* less_than_inst = builder.AddInstruction(MakeUnique<Instruction>(
context(), isEqualOp ? spv::Op::OpFOrdLessThan : spv::Op::OpFOrdGreaterThanEqual, context(), replacementOp, 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());

Some files were not shown because too many files have changed in this diff Show More