[Fix] (MG_Impl, MG_State, MG_Backend, MG_Util): Do source audit by Codex.

This commit is contained in:
BZLZHH
2026-06-09 15:34:19 +08:00
parent be3c3eb9bb
commit 727939af5b
93 changed files with 6019 additions and 731 deletions
+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
@@ -90,6 +90,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;
}; };
enum class WindowBackend { enum class WindowBackend {
@@ -97,6 +97,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);
} }
@@ -214,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;
@@ -415,7 +415,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
@@ -528,6 +537,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
@@ -546,6 +583,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
@@ -566,6 +607,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;
+38 -8
View File
@@ -614,10 +614,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);
g_GLESFuncs.glTexSubImage2D(glUploadTarget, static_cast<GLint>(level), 0, 0, const void* mipData = textureMipmapObject->MapMipmapData(uploadTarget, level);
static_cast<GLsizei>(texelSize.x()), switch (stateTextureObject->GetTarget()) {
static_cast<GLsizei>(texelSize.y()), glFormat, glType, case TextureTarget::Texture2D:
textureMipmapObject->MapMipmapData(uploadTarget, level)); case TextureTarget::TextureCubeMap:
g_GLESFuncs.glTexSubImage2D(glUploadTarget, static_cast<GLint>(level), 0, 0,
static_cast<GLsizei>(texelSize.x()),
static_cast<GLsizei>(texelSize.y()), glFormat, glType,
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);
} }
} }
@@ -912,7 +929,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
return false; return false;
} }
const auto& backendTextureObject = backendTextureIt->second; const auto& backendTextureObject = backendTextureIt->second;
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(),
@@ -1428,7 +1449,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;
@@ -1440,15 +1462,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);
g_GLESFuncs.glRenderbufferStorage(GL_RENDERBUFFER, glInternalFormat, static_cast<GLsizei>(width), if (samples > 0) {
static_cast<GLsizei>(height)); 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),
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);
@@ -313,6 +313,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());
} }
} }
@@ -207,5 +207,53 @@ namespace MobileGL::MG_Backend::DirectVulkan {
void BackendObject_DirectVulkan::UpdateDynamicBackendParameters() { void BackendObject_DirectVulkan::UpdateDynamicBackendParameters() {
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;
} }
} // namespace MobileGL::MG_Backend::DirectVulkan } // namespace MobileGL::MG_Backend::DirectVulkan
@@ -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,13 +212,13 @@ 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;
} }
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};
}; };
@@ -53,7 +53,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);
@@ -39,7 +39,25 @@ namespace MobileGL::MG_Backend::DirectVulkan {
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 +104,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,6 +129,8 @@ 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};
@@ -115,13 +141,31 @@ namespace MobileGL::MG_Backend::DirectVulkan {
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();
@@ -32,7 +32,20 @@ namespace MobileGL::MG_Backend::DirectVulkan {
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,19 @@
#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 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 +35,30 @@ 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,
.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() {
@@ -40,46 +75,46 @@ 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);
} }
} }
} }
@@ -94,7 +129,35 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return; return;
auto* pTexture = weakTexturePtr.lock().get(); auto* pTexture = weakTexturePtr.lock().get();
m_aliveObjects[pTexture] = weakTexturePtr; m_aliveObjects[pTexture] = weakTexturePtr;
auto& pending = m_pendingClears[pTexture]; auto& pending = m_pendingClears[MakePendingClearKey(pTexture)];
pending.mask |= clearPayload.mask;
if (clearPayload.mask & GL_COLOR_BUFFER_BIT) {
pending.color = clearPayload.color;
}
if (clearPayload.mask & GL_DEPTH_BUFFER_BIT) {
pending.depth = clearPayload.depth;
}
if (clearPayload.mask & GL_STENCIL_BUFFER_BIT) {
pending.stencil = clearPayload.stencil;
}
}
void VkClearManager::QueueClear(const ClearAttachmentPayload& clearPayload,
const MG_State::GLState::FramebufferAttachmentObject& attachment) {
if (clearPayload.mask == 0 || !attachment.IsTexture() || attachment.IsRenderbuffer()) {
return;
}
const auto texture = attachment.GetTexture();
if (!texture) {
return;
}
WeakPtr<MG_State::GLState::ITextureObject> weakTexturePtr = texture;
if (weakTexturePtr.expired()) {
return;
}
auto* pTexture = weakTexturePtr.lock().get();
m_aliveObjects[pTexture] = weakTexturePtr;
auto& pending = m_pendingClears[MakePendingClearKey(attachment)];
pending.mask |= clearPayload.mask; pending.mask |= clearPayload.mask;
if (clearPayload.mask & GL_COLOR_BUFFER_BIT) { if (clearPayload.mask & GL_COLOR_BUFFER_BIT) {
pending.color = clearPayload.color; pending.color = clearPayload.color;
@@ -108,20 +171,40 @@ namespace MobileGL::MG_Backend::DirectVulkan {
} }
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) {
return false;
}
return std::any_of(m_pendingClears.begin(), m_pendingClears.end(),
[texture](const auto& item) { return item.first.texture == texture; });
} }
Bool VkClearManager::GetPendingClear(MG_State::GLState::ITextureObject* texture, ClearAttachmentPayload& outPayload) { Bool VkClearManager::HasPendingClear(const PendingClearKey& key) {
if (m_aliveObjects.find(texture) == m_aliveObjects.end() || return key.texture != nullptr && m_pendingClears.find(key) != m_pendingClears.end();
m_pendingClears.find(texture) == m_pendingClears.end()) { }
MGLOG_D("%s: Failed getting pending clear for texture %d", __func__, texture->GetExternalIndex());
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) {
if (key.texture == nullptr || m_aliveObjects.find(key.texture) == m_aliveObjects.end()) {
return false;
}
auto it = m_pendingClears.find(key);
if (it == m_pendingClears.end()) {
MGLOG_D("%s: Failed getting pending clear for texture %d mip=%u layer=%u count=%u", __func__,
key.texture ? key.texture->GetExternalIndex() : 0, key.mipLevel, key.baseArrayLayer, key.layerCount);
return false; return false;
} }
outPayload = m_pendingClears[texture]; outPayload = it->second;
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__, MGLOG_D("%s: Got pending clear for texture %d (%s), mip=%u layer=%u count=%u mask=0x%x clear value: color = (%.2f, %.2f, %.2f, %.2f), depth = (%.2f), stencil = (%u)", __func__,
texture->GetExternalIndex(), key.texture->GetExternalIndex(),
MG_Util::ConvertTextureInternalFormatToString(texture->GetFormat()).c_str(), MG_Util::ConvertTextureInternalFormatToString(key.texture->GetFormat()).c_str(),
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,10 +212,59 @@ 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 || m_aliveObjects.find(texture) == m_aliveObjects.end()) {
return false;
}
for (const auto& [key, payload] : m_pendingClears) {
if (key.texture != texture) {
continue;
}
outEntries.emplace_back(PendingClearEntry{.key = key, .payload = payload});
}
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) {
return;
}
MGLOG_D("%s: Pop all pending clears for texture %d", __func__, texture->GetExternalIndex());
m_aliveObjects.erase(texture); m_aliveObjects.erase(texture);
m_pendingClears.erase(texture); for (auto it = m_pendingClears.begin(); it != m_pendingClears.end();) {
if (it->first.texture == texture) {
it = m_pendingClears.erase(it);
} else {
++it;
}
}
}
void VkClearManager::PopPendingClear(const PendingClearKey& key) {
if (key.texture == nullptr) {
return;
}
MGLOG_D("%s: Pop pending clear for texture %d mip=%u layer=%u count=%u", __func__,
key.texture->GetExternalIndex(), key.mipLevel, key.baseArrayLayer, key.layerCount);
m_pendingClears.erase(key);
}
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() {
@@ -145,7 +277,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
for (auto it = m_aliveObjects.begin(); it != m_aliveObjects.end();) { for (auto it = m_aliveObjects.begin(); it != m_aliveObjects.end();) {
auto current = it++; auto current = it++;
if (current->second.expired()) { if (current->second.expired()) {
m_pendingClears.erase(current->first); for (auto clearIt = m_pendingClears.begin(); clearIt != m_pendingClears.end();) {
if (clearIt->first.texture == current->first) {
clearIt = m_pendingClears.erase(clearIt);
} else {
++clearIt;
}
}
m_aliveObjects.erase(current); m_aliveObjects.erase(current);
++count; ++count;
} }
@@ -29,8 +29,43 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Uint32 stencil = 0; Uint32 stencil = 0;
}; };
struct PendingClearKey {
MG_State::GLState::ITextureObject* texture = nullptr;
Uint32 mipLevel = 0;
Uint32 baseArrayLayer = 0;
Uint32 layerCount = 1;
Bool operator==(const PendingClearKey& other) const {
return texture == other.texture && mipLevel == other.mipLevel &&
baseArrayLayer == other.baseArrayLayer && layerCount == other.layerCount;
}
};
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 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 ^= mipHash + 0x9e3779b9u + (hash << 6) + (hash >> 2);
hash ^= layerHash + 0x9e3779b9u + (hash << 6) + (hash >> 2);
hash ^= layerCountHash + 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 +73,22 @@ 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 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:
Uint8 m_gcCounter = 0; Uint8 m_gcCounter = 0;
UnorderedMap<MG_State::GLState::ITextureObject*, ClearAttachmentPayload> m_pendingClears; UnorderedMap<PendingClearKey, ClearAttachmentPayload, PendingClearKeyHash> m_pendingClears;
UnorderedMap<MG_State::GLState::ITextureObject*, WeakPtr<MG_State::GLState::ITextureObject>> m_aliveObjects; UnorderedMap<MG_State::GLState::ITextureObject*, WeakPtr<MG_State::GLState::ITextureObject>> 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,
@@ -79,6 +105,10 @@ 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(
@@ -117,6 +147,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
if (att.IsTexture()) { if (att.IsTexture()) {
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();
@@ -129,11 +161,12 @@ namespace MobileGL::MG_Backend::DirectVulkan {
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)));
@@ -180,18 +213,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;
} }
@@ -266,7 +299,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
texture2d->GetFormat()); texture2d->GetFormat());
desc.samples = VK_SAMPLE_COUNT_1_BIT; desc.samples = 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 :
@@ -280,7 +313,7 @@ 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)
}); });
} }
if (width == 0) if (width == 0)
@@ -313,7 +346,12 @@ namespace MobileGL::MG_Backend::DirectVulkan {
.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);
} }
@@ -340,19 +378,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 ?
@@ -396,7 +450,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) {
@@ -417,12 +471,18 @@ namespace MobileGL::MG_Backend::DirectVulkan {
.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");
if (width == 0 || height == 0) { if (width == 0 || height == 0) {
width = depthAtt.GetSize().x(); width = selectedDepthStencilAttachment->GetSize().x();
height = depthAtt.GetSize().y(); height = selectedDepthStencilAttachment->GetSize().y();
} }
} }
attachmentDescriptions.emplace_back(depthAttachmentDescription); attachmentDescriptions.emplace_back(depthAttachmentDescription);
@@ -439,7 +499,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;
@@ -512,11 +572,11 @@ 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)) { if (!s_clearManager->GetPendingClear(pending.key, clearPayload)) {
continue; continue;
} }
if ((clearPayload.mask & GL_COLOR_BUFFER_BIT) != 0) { if ((clearPayload.mask & GL_COLOR_BUFFER_BIT) != 0) {
@@ -524,7 +584,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(pending.key.texture, clearPayload.color.w())
}; };
} }
if ((clearPayload.mask & GL_DEPTH_BUFFER_BIT) != 0) { if ((clearPayload.mask & GL_DEPTH_BUFFER_BIT) != 0) {
@@ -540,7 +600,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;
@@ -26,7 +26,7 @@ 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 {
@@ -71,6 +71,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) {
@@ -594,7 +600,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 +609,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);
@@ -622,7 +675,7 @@ 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);
perMipSampledView = CreateImageView(resource->image, resource->format, resource->aspect, resource->viewType, perMipSampledView = CreateImageView(resource->image, resource->format, resource->aspect, 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);
@@ -1109,7 +1162,7 @@ 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, &sampledComponents); baseMipLevel, levelCount, 0, resource.arrayLayers, &sampledComponents);
if (resource.fullView == VK_NULL_HANDLE) { if (resource.fullView == VK_NULL_HANDLE) {
return false; return false;
} }
@@ -1122,6 +1175,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{};
@@ -1136,7 +1190,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;
@@ -1293,17 +1347,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)");
@@ -1331,7 +1386,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;
} }
@@ -30,11 +30,37 @@ 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;
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;
@@ -55,6 +81,7 @@ public:
std::swap(this->fullView, that.fullView); std::swap(this->fullView, that.fullView);
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);
@@ -82,12 +109,18 @@ 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);
} }
fullView = VK_NULL_HANDLE; fullView = 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;
@@ -118,6 +151,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,
@@ -146,6 +182,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,
@@ -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,
@@ -632,6 +704,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 +895,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 +922,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;
}; };
@@ -968,6 +1100,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;
return true; return true;
} }
@@ -990,6 +1124,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;
} }
@@ -1013,6 +1149,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 +1205,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 +1239,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;
} }
@@ -1123,6 +1265,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 +1323,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;
} }
@@ -2166,14 +2312,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};
@@ -2345,6 +2484,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) |
@@ -2366,19 +2515,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(
@@ -2555,6 +2737,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());
@@ -2686,14 +2872,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{};
@@ -2780,6 +2963,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(),
@@ -2794,6 +2981,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::QueueClearBufferPayload: draw framebuffer not found"); MOBILEGL_ASSERT(fbo, "VulkanRenderer::QueueClearBufferPayload: draw framebuffer not found");
if (IsUnsupportedFramebufferForDirectVulkan(*fbo)) {
RecordUnsupportedFramebufferError(__func__);
return;
}
auto queueAttachmentClear = [&](FramebufferAttachmentType attachmentType) { auto queueAttachmentClear = [&](FramebufferAttachmentType attachmentType) {
if (attachmentType == FramebufferAttachmentType::None) { if (attachmentType == FramebufferAttachmentType::None) {
@@ -2803,11 +2994,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) {
@@ -2920,8 +3107,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,
@@ -2940,53 +3127,65 @@ 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;
if ((resource->aspect & VK_IMAGE_ASPECT_COLOR_BIT) != 0) { for (const auto& pendingClear : pendingClears) {
subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; MOBILEGL_ASSERT(pendingClear.key.mipLevel < resource->mipLevels,
VkClearColorValue clearValue{}; "MaterializePendingClearForTexture: textureId=%d pending clear mip=%u out of range %u",
clearValue.float32[0] = clearPayload.color.x(); texture.GetExternalIndex(), pendingClear.key.mipLevel, resource->mipLevels);
clearValue.float32[1] = clearPayload.color.y(); MOBILEGL_ASSERT(pendingClear.key.baseArrayLayer + pendingClear.key.layerCount <= resource->arrayLayers,
clearValue.float32[2] = clearPayload.color.z(); "MaterializePendingClearForTexture: textureId=%d pending clear layer span [%u, %u) exceeds arrayLayers=%u",
clearValue.float32[3] = ResolveColorClearAlpha(&texture, clearPayload.color.w()); texture.GetExternalIndex(), pendingClear.key.baseArrayLayer,
vkCmdClearColorImage(commandBuffer, resource->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, pendingClear.key.baseArrayLayer + pendingClear.key.layerCount, resource->arrayLayers);
&clearValue, 1, &subresourceRange);
} else { VkImageSubresourceRange subresourceRange{};
VkImageAspectFlags clearAspectMask = 0; subresourceRange.baseMipLevel = pendingClear.key.mipLevel;
if ((resource->aspect & VK_IMAGE_ASPECT_DEPTH_BIT) != 0 && subresourceRange.levelCount = 1;
(clearPayload.mask & GL_DEPTH_BUFFER_BIT) != 0) { subresourceRange.baseArrayLayer = pendingClear.key.baseArrayLayer;
clearAspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT; subresourceRange.layerCount = pendingClear.key.layerCount;
const auto& clearPayload = pendingClear.payload;
if ((resource->aspect & VK_IMAGE_ASPECT_COLOR_BIT) != 0) {
subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
VkClearColorValue clearValue{};
clearValue.float32[0] = clearPayload.color.x();
clearValue.float32[1] = clearPayload.color.y();
clearValue.float32[2] = clearPayload.color.z();
clearValue.float32[3] = ResolveColorClearAlpha(&texture, clearPayload.color.w());
vkCmdClearColorImage(commandBuffer, resource->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
&clearValue, 1, &subresourceRange);
} else {
VkImageAspectFlags clearAspectMask = 0;
if ((resource->aspect & VK_IMAGE_ASPECT_DEPTH_BIT) != 0 &&
(clearPayload.mask & GL_DEPTH_BUFFER_BIT) != 0) {
clearAspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
}
if ((resource->aspect & VK_IMAGE_ASPECT_STENCIL_BIT) != 0 &&
(clearPayload.mask & GL_STENCIL_BUFFER_BIT) != 0) {
clearAspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
}
MOBILEGL_ASSERT(clearAspectMask != 0,
"MaterializePendingClearForTexture: textureId=%d has no matching depth/stencil clear mask",
texture.GetExternalIndex());
subresourceRange.aspectMask = clearAspectMask;
VkClearDepthStencilValue clearValue{};
clearValue.depth = clearPayload.depth;
clearValue.stencil = clearPayload.stencil;
vkCmdClearDepthStencilImage(commandBuffer, resource->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
&clearValue, 1, &subresourceRange);
sampledLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
} }
if ((resource->aspect & VK_IMAGE_ASPECT_STENCIL_BIT) != 0 &&
(clearPayload.mask & GL_STENCIL_BUFFER_BIT) != 0) {
clearAspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
}
MOBILEGL_ASSERT(clearAspectMask != 0,
"MaterializePendingClearForTexture: textureId=%d has no matching depth/stencil clear mask",
texture.GetExternalIndex());
subresourceRange.aspectMask = clearAspectMask;
VkClearDepthStencilValue clearValue{};
clearValue.depth = clearPayload.depth;
clearValue.stencil = clearPayload.stencil;
vkCmdClearDepthStencilImage(commandBuffer, resource->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
&clearValue, 1, &subresourceRange);
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());
@@ -3054,14 +3253,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};
@@ -3163,6 +3355,11 @@ void main() {
auto drawFbo = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject(); auto drawFbo = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
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) {
@@ -3285,13 +3482,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};
@@ -3421,14 +3618,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) {
@@ -3503,6 +3700,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) {
@@ -3601,13 +3803,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,
@@ -4064,7 +4266,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());
@@ -4350,8 +4553,11 @@ 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;
VkDeviceCreateInfo deviceCreateInfo{}; VkDeviceCreateInfo deviceCreateInfo{};
deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
@@ -4416,16 +4622,20 @@ 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", MGLOG_I("Device feature support: geometryShader=%s independentBlend=%s logicOp=%s shaderClipDistance=%s shaderCullDistance=%s wideLines=%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",
MGLOG_I("Device feature enabled: geometryShader=%s independentBlend=%s shaderClipDistance=%s shaderCullDistance=%s", supportedDeviceFeatures.wideLines ? "true" : "false");
MGLOG_I("Device feature enabled: geometryShader=%s independentBlend=%s logicOp=%s shaderClipDistance=%s shaderCullDistance=%s wideLines=%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");
VK_VERIFY(vkCreateDevice(m_physicalDevice.handle, &deviceCreateInfo, nullptr, &m_device), "vkCreateDevice"); VK_VERIFY(vkCreateDevice(m_physicalDevice.handle, &deviceCreateInfo, nullptr, &m_device), "vkCreateDevice");
s_vkCmdDrawIndexedIndirectCount = reinterpret_cast<PFNDrawIndexedIndirectCountFunc>( s_vkCmdDrawIndexedIndirectCount = reinterpret_cast<PFNDrawIndexedIndirectCountFunc>(
@@ -4726,12 +4936,12 @@ 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)) { if (!m_clearManager->GetPendingClear(pending.key, clearPayload)) {
continue; continue;
} }
@@ -4744,7 +4954,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(pending.key.texture, clearPayload.color.w())
}; };
} else { } else {
if ((clearPayload.mask & GL_DEPTH_BUFFER_BIT) != 0) { if ((clearPayload.mask & GL_DEPTH_BUFFER_BIT) != 0) {
@@ -4761,7 +4971,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);
} }
} }
@@ -195,6 +195,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;
} }
+120 -11
View File
@@ -80,6 +80,93 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
} }
void GetBufferPointerv_State(GLenum target, GLenum pname, void** params) {
if (!params) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetBufferPointerv_State",
"Params pointer cannot be null."));
return;
}
BufferTarget bufferTarget = MG_Util::ConvertGLEnumToBufferTarget(target);
if (!BufferImpl::ValidateBufferTarget(bufferTarget)) return;
auto& bindingSlot = GetBufferBindingSlot(bufferTarget);
auto& bufferObject = bindingSlot.GetBoundObject();
if (!bufferObject) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetBufferPointerv_State",
"Buffer target is bound to no buffer object."));
return;
}
if (pname != GL_BUFFER_MAP_POINTER) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetBufferPointerv_State",
std::format("Invalid pname enum: 0x{:X}", pname)));
return;
}
*params = bufferObject->GetMappedPointer();
}
void GetBufferParameteri64v_State(GLenum target, GLenum pname, GLint64* params) {
if (!params) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetBufferParameteri64v_State",
"Params pointer cannot be null."));
return;
}
BufferTarget bufferTarget = MG_Util::ConvertGLEnumToBufferTarget(target);
if (!BufferImpl::ValidateBufferTarget(bufferTarget)) return;
auto& bindingSlot = GetBufferBindingSlot(bufferTarget);
auto& bufferObject = bindingSlot.GetBoundObject();
if (!bufferObject) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetBufferParameteri64v_State",
"Buffer target is bound to no buffer object."));
return;
}
switch (pname) {
case GL_BUFFER_SIZE:
*params = static_cast<GLint64>(bufferObject->GetSize());
break;
case GL_BUFFER_USAGE:
*params = static_cast<GLint64>(MG_Util::ConvertBufferUsageToGLEnum(bufferObject->GetUsage()));
break;
case GL_BUFFER_ACCESS:
if (bufferObject->IsMapped()) {
auto access = bufferObject->GetMappingAccess();
if (access & BufferMappingAccessBit::Read && access & BufferMappingAccessBit::Write) {
*params = GL_READ_WRITE;
} else if (access & BufferMappingAccessBit::Read) {
*params = GL_READ_ONLY;
} else if (access & BufferMappingAccessBit::Write) {
*params = GL_WRITE_ONLY;
} else {
*params = 0;
}
} else {
*params = 0;
}
break;
case GL_BUFFER_MAPPED:
*params = bufferObject->IsMapped() ? GL_TRUE : GL_FALSE;
break;
default:
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetBufferParameteri64v_State",
std::format("Invalid pname enum: 0x{:X}", pname)));
break;
}
}
void DeleteBuffers_State(GLsizei n, const GLuint* buffers) { void DeleteBuffers_State(GLsizei n, const GLuint* buffers) {
if (n < 0) { if (n < 0) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
@@ -524,16 +611,23 @@ namespace MobileGL::MG_Impl::GLImpl {
BufferTarget bufferTarget = MG_Util::ConvertGLEnumToBufferTarget(target); BufferTarget bufferTarget = MG_Util::ConvertGLEnumToBufferTarget(target);
if (!BufferImpl::ValidateBufferBindingPointTarget(bufferTarget)) return; if (!BufferImpl::ValidateBufferBindingPointTarget(bufferTarget)) return;
Bool doesBufferObjectCreated = MG_State::pGLContext->ValidateBufferObject(buffer); SharedPtr<MG_State::GLState::BufferObject> bufferObject;
if (!doesBufferObjectCreated) { if (buffer != 0) {
MG_State::pGLContext->CreateBufferObject(buffer); Bool doesBufferObjectCreated = MG_State::pGLContext->ValidateBufferObject(buffer);
if (!doesBufferObjectCreated) {
MG_State::pGLContext->CreateBufferObject(buffer);
}
bufferObject = MG_State::pGLContext->GetBufferObject(buffer);
} }
auto& bufferObject = MG_State::pGLContext->GetBufferObject(buffer);
auto& point = MG_State::pGLContext->GetBufferBindingPoint(bufferTarget, pointIndex); auto& point = MG_State::pGLContext->GetBufferBindingPoint(bufferTarget, pointIndex);
point.Bind(bufferObject); point.Bind(bufferObject);
point.SetRange(Range1D(0, bufferObject->GetSize())); if (bufferObject) {
MGLOG_D("%s: set range (0, %d)", __func__, bufferObject->GetSize()); point.SetRange(Range1D(0, 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) {
@@ -542,15 +636,22 @@ namespace MobileGL::MG_Impl::GLImpl {
BufferTarget bufferTarget = MG_Util::ConvertGLEnumToBufferTarget(target); BufferTarget bufferTarget = MG_Util::ConvertGLEnumToBufferTarget(target);
if (!BufferImpl::ValidateBufferBindingPointTarget(bufferTarget)) return; if (!BufferImpl::ValidateBufferBindingPointTarget(bufferTarget)) return;
Bool doesBufferObjectCreated = MG_State::pGLContext->ValidateBufferObject(buffer); SharedPtr<MG_State::GLState::BufferObject> bufferObject;
if (!doesBufferObjectCreated) { if (buffer != 0) {
MG_State::pGLContext->CreateBufferObject(buffer); Bool doesBufferObjectCreated = MG_State::pGLContext->ValidateBufferObject(buffer);
if (!doesBufferObjectCreated) {
MG_State::pGLContext->CreateBufferObject(buffer);
}
bufferObject = MG_State::pGLContext->GetBufferObject(buffer);
} }
auto& bufferObject = MG_State::pGLContext->GetBufferObject(buffer);
auto& point = MG_State::pGLContext->GetBufferBindingPoint(bufferTarget, index); auto& point = MG_State::pGLContext->GetBufferBindingPoint(bufferTarget, index);
point.Bind(bufferObject); point.Bind(bufferObject);
point.SetRange(Range1D(offset, offset + size)); if (bufferObject) {
point.SetRange(Range1D(offset, offset + size));
} else {
point.ClearRange();
}
} }
/* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */ /* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */
@@ -558,6 +659,14 @@ namespace MobileGL::MG_Impl::GLImpl {
GetBufferParameteriv_State(target, pname, params); GetBufferParameteriv_State(target, pname, params);
} }
void GetBufferPointerv(GLenum target, GLenum pname, void** 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,8 @@
namespace MobileGL::MG_Impl::GLImpl { namespace MobileGL::MG_Impl::GLImpl {
/* @INSERTION_POINT:FUNCTION_DECLARATION@ */ /* @INSERTION_POINT:FUNCTION_DECLARATION@ */
void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params); void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params);
void GetBufferParameteri64v(GLenum target, GLenum pname, GLint64* params);
void GetBufferPointerv(GLenum target, GLenum pname, void** params);
GLboolean IsBuffer(GLuint buffer); GLboolean IsBuffer(GLuint buffer);
void DeleteBuffers(GLsizei n, const GLuint* buffers); void DeleteBuffers(GLsizei n, const GLuint* buffers);
void FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length); void FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length);
@@ -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);
@@ -164,6 +220,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);
} }
@@ -176,6 +233,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);
} }
@@ -203,74 +261,106 @@ 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);
} }
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);
} }
@@ -279,6 +369,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);
} }
@@ -16,6 +16,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__) {
@@ -75,7 +76,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)
@@ -94,7 +95,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)
@@ -116,10 +117,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)
@@ -134,9 +135,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)
@@ -189,14 +190,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)
@@ -214,7 +215,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, EndQuery, GLenum target) DECLARE_GL_FUNCTION
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetQueryiv, GLenum target, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetQueryiv, target, pname, params) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetQueryiv, GLenum target, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetQueryiv, target, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetQueryObjectuiv, GLuint id, GLenum pname, GLuint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetQueryObjectuiv, id, pname, params) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetQueryObjectuiv, GLuint id, GLenum pname, GLuint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetQueryObjectuiv, id, pname, params)
DECLARE_GL_FUNCTION_HEAD(GLboolean, UnmapBuffer, GLenum target) DECLARE_GL_FUNCTION_END(GLboolean, UnmapBuffer, target) DECLARE_GL_FUNCTION_HEAD(GLboolean, UnmapBuffer, GLenum target) DECLARE_GL_FUNCTION_END(GLboolean, UnmapBuffer, target)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetBufferPointerv, GLenum target, GLenum pname, void** params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetBufferPointerv, target, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetBufferPointerv, GLenum target, GLenum pname, void** params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetBufferPointerv, target, pname, params)
DECLARE_GL_FUNCTION_HEAD(void, DrawBuffers, GLsizei n, const GLenum* bufs) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DrawBuffers, n, bufs) DECLARE_GL_FUNCTION_HEAD(void, DrawBuffers, GLsizei n, const GLenum* bufs) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DrawBuffers, n, bufs)
DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformMatrix2x3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformMatrix2x3fv, location, count, transpose, value) DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformMatrix2x3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformMatrix2x3fv, location, count, transpose, value)
DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformMatrix3x2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformMatrix3x2fv, location, count, transpose, value) DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformMatrix3x2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformMatrix3x2fv, location, count, transpose, value)
@@ -239,28 +240,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_STUB_HEAD(void, Uniform1ui, GLint location, GLuint v0) DECLARE_GL_FUNCTION_STUB_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_STUB_HEAD(void, Uniform1uiv, GLint location, GLsizei count, const GLuint* value) DECLARE_GL_FUNCTION_STUB_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)
@@ -268,15 +269,15 @@ DECLARE_GL_FUNCTION_HEAD(void, GetActiveUniformBlockName, GLuint program, GLuint
DECLARE_GL_FUNCTION_HEAD(void, UniformBlockBinding, GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformBlockBinding, program, uniformBlockIndex, uniformBlockBinding) DECLARE_GL_FUNCTION_HEAD(void, UniformBlockBinding, GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformBlockBinding, program, uniformBlockIndex, uniformBlockBinding)
DECLARE_GL_FUNCTION_HEAD(void, DrawArraysInstanced, GLenum mode, GLint first, GLsizei count, GLsizei instancecount) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DrawArraysInstanced, mode, first, count, instancecount) DECLARE_GL_FUNCTION_HEAD(void, DrawArraysInstanced, GLenum mode, GLint first, GLsizei count, GLsizei instancecount) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DrawArraysInstanced, mode, first, count, instancecount)
DECLARE_GL_FUNCTION_HEAD(void, DrawElementsInstanced, GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instancecount) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DrawElementsInstanced, mode, count, type, indices, instancecount) DECLARE_GL_FUNCTION_HEAD(void, DrawElementsInstanced, GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instancecount) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DrawElementsInstanced, mode, count, type, indices, instancecount)
DECLARE_GL_FUNCTION_STUB_HEAD(GLsync, FenceSync, GLenum condition, GLbitfield flags) DECLARE_GL_FUNCTION_STUB_END(GLsync, FenceSync, condition, flags) DECLARE_GL_FUNCTION_HEAD(GLsync, FenceSync, GLenum condition, GLbitfield flags) DECLARE_GL_FUNCTION_END(GLsync, FenceSync, condition, flags)
DECLARE_GL_FUNCTION_STUB_HEAD(GLboolean, IsSync, GLsync sync) DECLARE_GL_FUNCTION_STUB_END(GLboolean, IsSync, sync) DECLARE_GL_FUNCTION_HEAD(GLboolean, IsSync, GLsync sync) DECLARE_GL_FUNCTION_END(GLboolean, IsSync, sync)
DECLARE_GL_FUNCTION_STUB_HEAD(void, DeleteSync, GLsync sync) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DeleteSync, sync) DECLARE_GL_FUNCTION_HEAD(void, DeleteSync, GLsync sync) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DeleteSync, sync)
DECLARE_GL_FUNCTION_STUB_HEAD(GLenum, ClientWaitSync, GLsync sync, GLbitfield flags, GLuint64 timeout) DECLARE_GL_FUNCTION_STUB_END(GLenum, ClientWaitSync, sync, flags, timeout) DECLARE_GL_FUNCTION_HEAD(GLenum, ClientWaitSync, GLsync sync, GLbitfield flags, GLuint64 timeout) DECLARE_GL_FUNCTION_END(GLenum, ClientWaitSync, sync, flags, timeout)
DECLARE_GL_FUNCTION_STUB_HEAD(void, WaitSync, GLsync sync, GLbitfield flags, GLuint64 timeout) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, WaitSync, sync, flags, timeout) DECLARE_GL_FUNCTION_HEAD(void, WaitSync, GLsync sync, GLbitfield flags, GLuint64 timeout) DECLARE_GL_FUNCTION_END_NO_RETURN(void, WaitSync, sync, flags, timeout)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetInteger64v, GLenum pname, GLint64* data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetInteger64v, pname, data) DECLARE_GL_FUNCTION_HEAD(void, GetInteger64v, GLenum pname, GLint64* data) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetInteger64v, pname, data)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetSynciv, GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetSynciv, sync, pname, bufSize, length, values) DECLARE_GL_FUNCTION_HEAD(void, GetSynciv, GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetSynciv, sync, pname, bufSize, length, values)
DECLARE_GL_FUNCTION_HEAD(void, GetInteger64i_v, GLenum target, GLuint index, GLint64* data) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetInteger64i_v, target, index, data) DECLARE_GL_FUNCTION_HEAD(void, GetInteger64i_v, GLenum target, GLuint index, GLint64* data) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetInteger64i_v, target, index, data)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetBufferParameteri64v, GLenum target, GLenum pname, GLint64* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetBufferParameteri64v, target, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetBufferParameteri64v, GLenum target, GLenum pname, GLint64* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetBufferParameteri64v, target, pname, params)
DECLARE_GL_FUNCTION_HEAD(void, GenSamplers, GLsizei count, GLuint* samplers) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GenSamplers, count, samplers) DECLARE_GL_FUNCTION_HEAD(void, GenSamplers, GLsizei count, GLuint* samplers) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GenSamplers, count, samplers)
DECLARE_GL_FUNCTION_HEAD(void, DeleteSamplers, GLsizei count, const GLuint* samplers) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DeleteSamplers, count, samplers) DECLARE_GL_FUNCTION_HEAD(void, DeleteSamplers, GLsizei count, const GLuint* samplers) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DeleteSamplers, count, samplers)
DECLARE_GL_FUNCTION_HEAD(GLboolean, IsSampler, GLuint sampler) DECLARE_GL_FUNCTION_END(GLboolean, IsSampler, sampler) DECLARE_GL_FUNCTION_HEAD(GLboolean, IsSampler, GLuint sampler) DECLARE_GL_FUNCTION_END(GLboolean, IsSampler, sampler)
@@ -357,7 +358,7 @@ 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_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)
@@ -829,8 +830,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)
@@ -839,11 +840,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_STUB_HEAD(void, ProvokingVertex, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProvokingVertex, mode) DECLARE_GL_FUNCTION_STUB_HEAD(void, ProvokingVertex, GLenum mode) DECLARE_GL_FUNCTION_STUB_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)
@@ -1489,9 +1490,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)
@@ -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,
@@ -26,12 +160,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 RenderbufferStorage_State(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) { void RenderbufferStorage_State(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
@@ -56,14 +231,15 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
renderbufferObject->AllocateStorage({width, height}); renderbufferObject->AllocateStorage({width, height});
renderbufferObject->SetInternalFormat(format); renderbufferObject->SetInternalFormat(format);
renderbufferObject->SetSamples(0);
} }
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) {
@@ -136,6 +312,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;
@@ -174,12 +370,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) {
@@ -199,6 +414,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();
@@ -224,15 +444,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) {
// TODO: implement 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 FramebufferRenderbuffer_State(GLenum target, GLenum attachment, GLenum renderbuffertarget, void FramebufferRenderbuffer_State(GLenum target, GLenum attachment, GLenum renderbuffertarget,
@@ -246,7 +510,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) {
@@ -290,6 +555,12 @@ namespace MobileGL::MG_Impl::GLImpl {
// Get bound framebuffer // Get bound framebuffer
auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw); auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw);
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 draw target."));
return;
}
bool isDefaultFBO = (fbo == FramebufferImpl::pDefaultFramebufferInfo->defaultFBO); bool isDefaultFBO = (fbo == FramebufferImpl::pDefaultFramebufferInfo->defaultFBO);
static int existenceMap[(SizeT)FramebufferAttachmentType::FramebufferAttachmentTypeCount] = {-1}; static int existenceMap[(SizeT)FramebufferAttachmentType::FramebufferAttachmentTypeCount] = {-1};
@@ -308,20 +579,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>(
@@ -388,6 +659,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);
} }
@@ -453,24 +761,35 @@ 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;
} }
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);
} }
@@ -567,7 +886,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);
@@ -576,7 +895,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
@@ -584,7 +903,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
@@ -592,7 +911,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
@@ -603,7 +922,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
@@ -611,7 +930,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
@@ -621,7 +940,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()) {
@@ -629,7 +948,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() ||
@@ -638,7 +957,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
@@ -647,7 +966,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;
} }
} }
@@ -661,7 +980,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
@@ -671,7 +990,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;
} }
} }
@@ -683,9 +1002,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) {
@@ -694,7 +1015,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);
} }
File diff suppressed because it is too large Load Diff
@@ -13,7 +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* 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();
+232 -125
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>(
"location " + std::to_string(location) + "MG_Impl/GLImpl", __func__,
" does not correspond to a valid uniform variable location " "location " + std::to_string(location) +
"for the specified program object.")); " does not correspond to a valid uniform variable location 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) {
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 (GLint offset = 0; offset < count; offset++) { for (GLint offset = 0; offset < count; offset++) {
if (!programObject->IsValidUniformLocation(location + offset)) {
RecordInvalidUniformLocationError(__func__, location + offset, "the current program object");
return;
}
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) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"location " + std::to_string(location) +
" is an invalid uniform location for program " +
std::to_string(program) + "."));
return;
}
for (GLint offset = 0; offset < count; offset++) { for (GLint offset = 0; offset < count; offset++) {
if (!programObject->IsValidUniformLocation(location + offset)) {
RecordInvalidUniformLocationError(__func__, location + offset,
"program " + std::to_string(program));
return;
}
Uniform_State<ItemCount>(*programObject, location + offset, value + offset * ItemCount); Uniform_State<ItemCount>(*programObject, location + offset, value + offset * ItemCount);
} }
} }
@@ -744,19 +811,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];
@@ -782,20 +842,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];
@@ -825,19 +878,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];
@@ -865,17 +911,11 @@ 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 program " +
std::to_string(program) + "."));
return;
}
for (GLint i = 0; i < count; i++) { for (GLint i = 0; i < count; i++) {
if (!programObject->IsValidUniformLocation(location + i)) {
RecordInvalidUniformLocationError(__func__, location + i, "program " + std::to_string(program));
return;
}
if (transpose == GL_TRUE) { if (transpose == GL_TRUE) {
GLfloat transposedMatrix[4]; GLfloat transposedMatrix[4];
TransposeMatrix2x2(value + i * 4, transposedMatrix); TransposeMatrix2x2(value + i * 4, transposedMatrix);
@@ -901,17 +941,11 @@ 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 program " +
std::to_string(program) + "."));
return;
}
for (GLint i = 0; i < count; i++) { for (GLint i = 0; i < count; i++) {
if (!programObject->IsValidUniformLocation(location + i)) {
RecordInvalidUniformLocationError(__func__, location + i, "program " + std::to_string(program));
return;
}
if (transpose == GL_TRUE) { if (transpose == GL_TRUE) {
GLfloat transposedMatrix[9]; GLfloat transposedMatrix[9];
TransposeMatrix3x3(value + i * 9, transposedMatrix); TransposeMatrix3x3(value + i * 9, transposedMatrix);
@@ -941,17 +975,11 @@ 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 program " +
std::to_string(program) + "."));
return;
}
for (GLint i = 0; i < count; i++) { for (GLint i = 0; i < count; i++) {
if (!programObject->IsValidUniformLocation(location + i)) {
RecordInvalidUniformLocationError(__func__, location + i, "program " + std::to_string(program));
return;
}
if (transpose == GL_TRUE) { if (transpose == GL_TRUE) {
GLfloat transposedMatrix[16]; GLfloat transposedMatrix[16];
TransposeMatrix4x4(value + i * 16, transposedMatrix); TransposeMatrix4x4(value + i * 16, transposedMatrix);
@@ -1033,22 +1061,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(
@@ -1084,7 +1142,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) {
@@ -1166,6 +1224,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);
} }
@@ -1206,6 +1274,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);
} }
@@ -1263,6 +1335,25 @@ namespace MobileGL::MG_Impl::GLImpl {
Uniform4iv(location, 1, v); Uniform4iv(location, 1, v);
} }
void Uniform1ui(GLint location, GLuint 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);
} }
@@ -1295,6 +1386,22 @@ namespace MobileGL::MG_Impl::GLImpl {
Uniform4iv_State(location, count, value); Uniform4iv_State(location, count, value);
} }
void Uniform1uiv(GLint location, GLsizei count, const GLuint* 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) {
UniformMatrix2fv_State(location, count, transpose, value); UniformMatrix2fv_State(location, count, transpose, 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);
@@ -45,6 +50,10 @@ namespace MobileGL::MG_Impl::GLImpl {
void Uniform2i(GLint location, GLint v0, GLint v1); void Uniform2i(GLint location, GLint v0, GLint v1);
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 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);
@@ -53,6 +62,10 @@ namespace MobileGL::MG_Impl::GLImpl {
void Uniform2iv(GLint location, GLsizei count, const GLint* value); void Uniform2iv(GLint location, GLsizei count, const GLint* value);
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 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) {
@@ -197,7 +349,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) {
@@ -289,7 +442,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) {
@@ -359,6 +513,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(
@@ -373,6 +531,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(
@@ -403,6 +565,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);
+213 -9
View File
@@ -9,35 +9,239 @@
#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>
namespace MobileGL::MG_Impl::GLImpl { namespace MobileGL::MG_Impl::GLImpl {
namespace {
const MG_External::GLESFunctionsTable* TryGetDirectGLESFunctions(const char* funcName) {
auto* activeBackend = MG_Backend::pActiveBackendObject.get();
if (!activeBackend) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", funcName, "No active backend object."));
return nullptr;
}
auto* directGLESBackend =
dynamic_cast<MG_Backend::DirectGLES::BackendObject_DirectGLES*>(activeBackend);
if (!directGLESBackend) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", funcName,
"Sync objects are only implemented for the DirectGLES backend."));
return nullptr;
}
return &directGLESBackend->GetGLESFunctions();
}
Bool ValidateFenceSyncArgs(const char* funcName, GLenum condition, GLbitfield flags) {
if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", funcName,
"condition must be GL_SYNC_GPU_COMMANDS_COMPLETE."));
return false;
}
if (flags != 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", funcName, "flags must be zero."));
return false;
}
return true;
}
Bool ValidateSyncHandle(const char* funcName, GLsync sync) {
if (sync != nullptr) {
return true;
}
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", funcName, "sync must be a valid non-null handle."));
return false;
}
}
GLsync FenceSync_Backend(GLenum condition, GLbitfield flags) { GLsync FenceSync_Backend(GLenum condition, GLbitfield flags) {
return 0; const auto* glesFuncs = TryGetDirectGLESFunctions(__func__);
if (!glesFuncs || !glesFuncs->glFenceSync) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"Backend does not expose glFenceSync."));
return nullptr;
}
return glesFuncs->glFenceSync(condition, flags);
}
GLboolean IsSync_Backend(GLsync sync) {
const auto* glesFuncs = TryGetDirectGLESFunctions(__func__);
if (!glesFuncs || !glesFuncs->glIsSync) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"Backend does not expose glIsSync."));
return GL_FALSE;
}
return glesFuncs->glIsSync(sync);
} }
GLenum ClientWaitSync_Backend(GLsync sync, GLbitfield flags, GLuint64 timeout) { GLenum ClientWaitSync_Backend(GLsync sync, GLbitfield flags, GLuint64 timeout) {
return 0; const auto* glesFuncs = TryGetDirectGLESFunctions(__func__);
if (!glesFuncs || !glesFuncs->glClientWaitSync) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"Backend does not expose glClientWaitSync."));
return GL_WAIT_FAILED;
}
return glesFuncs->glClientWaitSync(sync, flags, timeout);
} }
void DeleteSync_Backend(GLsync sync) {} void WaitSync_Backend(GLsync sync, GLbitfield flags, GLuint64 timeout) {
const auto* glesFuncs = TryGetDirectGLESFunctions(__func__);
if (!glesFuncs || !glesFuncs->glWaitSync) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"Backend does not expose glWaitSync."));
return;
}
glesFuncs->glWaitSync(sync, flags, timeout);
}
void GetSynciv_Backend(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values) {
const auto* glesFuncs = TryGetDirectGLESFunctions(__func__);
if (!glesFuncs || !glesFuncs->glGetSynciv) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"Backend does not expose glGetSynciv."));
return;
}
glesFuncs->glGetSynciv(sync, pname, bufSize, length, values);
}
void DeleteSync_Backend(GLsync sync) {
const auto* glesFuncs = TryGetDirectGLESFunctions(__func__);
if (!glesFuncs || !glesFuncs->glDeleteSync) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"Backend does not expose glDeleteSync."));
return;
}
glesFuncs->glDeleteSync(sync);
}
GLsync FenceSync_State(GLenum condition, GLbitfield flags) { GLsync FenceSync_State(GLenum condition, GLbitfield flags) {
return 0; if (!ValidateFenceSyncArgs(__func__, condition, flags)) {
return nullptr;
}
return FenceSync_Backend(condition, flags);
}
GLboolean IsSync_State(GLsync sync) {
if (sync == nullptr) return GL_FALSE;
return IsSync_Backend(sync);
} }
GLenum ClientWaitSync_State(GLsync sync, GLbitfield flags, GLuint64 timeout) { GLenum ClientWaitSync_State(GLsync sync, GLbitfield flags, GLuint64 timeout) {
return 0; (void)timeout;
if (!ValidateSyncHandle(__func__, sync)) {
return GL_WAIT_FAILED;
}
if ((flags & ~GL_SYNC_FLUSH_COMMANDS_BIT) != 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"flags contains unsupported bits."));
return GL_WAIT_FAILED;
}
return ClientWaitSync_Backend(sync, flags, timeout);
} }
void DeleteSync_State(GLsync sync) {} void WaitSync_State(GLsync sync, GLbitfield flags, GLuint64 timeout) {
if (!ValidateSyncHandle(__func__, sync)) {
return;
}
if (flags != 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "flags must be zero."));
return;
}
if (timeout != GL_TIMEOUT_IGNORED) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "timeout must be GL_TIMEOUT_IGNORED."));
return;
}
WaitSync_Backend(sync, flags, timeout);
}
void GetSynciv_State(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values) {
if (!ValidateSyncHandle(__func__, sync)) {
return;
}
if (bufSize < 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "bufSize must be non-negative."));
return;
}
if (bufSize > 0 && values == nullptr) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"values must not be null when bufSize is positive."));
return;
}
switch (pname) {
case GL_OBJECT_TYPE:
case GL_SYNC_CONDITION:
case GL_SYNC_STATUS:
case GL_SYNC_FLAGS:
break;
default:
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "Unsupported sync pname."));
return;
}
GetSynciv_Backend(sync, pname, bufSize, length, values);
}
void DeleteSync_State(GLsync sync) {
if (sync == nullptr) return;
DeleteSync_Backend(sync);
}
GLsync FenceSync(GLenum condition, GLbitfield flags) { GLsync FenceSync(GLenum condition, GLbitfield flags) {
return 0; return FenceSync_State(condition, flags);
}
GLboolean IsSync(GLsync sync) {
return IsSync_State(sync);
} }
GLenum ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) { GLenum ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) {
return 0; return ClientWaitSync_State(sync, flags, timeout);
} }
void DeleteSync(GLsync sync) {} void WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) {
WaitSync_State(sync, flags, timeout);
}
void GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values) {
GetSynciv_State(sync, pname, bufSize, length, values);
}
void DeleteSync(GLsync sync) {
DeleteSync_State(sync);
}
} // namespace MobileGL::MG_Impl::GLImpl } // namespace MobileGL::MG_Impl::GLImpl
+3
View File
@@ -11,6 +11,9 @@
namespace MobileGL::MG_Impl::GLImpl { namespace MobileGL::MG_Impl::GLImpl {
GLsync FenceSync(GLenum condition, GLbitfield flags); GLsync FenceSync(GLenum condition, GLbitfield flags);
GLboolean IsSync(GLsync sync);
void WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout);
GLenum ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout); GLenum ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout);
void GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values);
void DeleteSync(GLsync sync); void DeleteSync(GLsync sync);
} // namespace MobileGL::MG_Impl::GLImpl } // namespace MobileGL::MG_Impl::GLImpl
+128 -36
View File
@@ -31,6 +31,21 @@ namespace MobileGL::MG_Impl::GLImpl {
static SharedPtr<MG_State::GLState::ITextureObject> nullTextureObject; static SharedPtr<MG_State::GLState::ITextureObject> nullTextureObject;
static UnorderedMap<Uint, Bool> g_autoGenerateMipmapByTextureId; static UnorderedMap<Uint, Bool> g_autoGenerateMipmapByTextureId;
void GetTexParameteriv_State(GLenum target, GLenum pname, GLint* params);
namespace {
void SetTextureBorderColorFromFloats(const SharedPtr<MG_State::GLState::ITextureObject>& textureObject,
const GLfloat* params) {
textureObject->SetBorderColor(FloatVec4(params[0], params[1], params[2], params[3]));
}
void SetTextureBorderColorFromInts(const SharedPtr<MG_State::GLState::ITextureObject>& textureObject,
const GLint* params) {
textureObject->SetBorderColor(FloatVec4(static_cast<Float>(params[0]), static_cast<Float>(params[1]),
static_cast<Float>(params[2]), static_cast<Float>(params[3])));
}
} // namespace
const SharedPtr<MG_State::GLState::ITextureObject>& GetTextureObjectByTarget( const SharedPtr<MG_State::GLState::ITextureObject>& GetTextureObjectByTarget(
TextureUploadTarget textureUploadTarget, TextureTarget textureTarget) { TextureUploadTarget textureUploadTarget, TextureTarget textureTarget) {
if (TextureImpl::IsProxyTextureTarget(textureUploadTarget)) { if (TextureImpl::IsProxyTextureTarget(textureUploadTarget)) {
@@ -360,7 +375,7 @@ namespace MobileGL::MG_Impl::GLImpl {
// ======================= Processing ================================ // ======================= Processing ================================
auto& textureObject = GetTextureObjectByTarget(textureUploadTarget, textureTarget); auto& textureObject = GetTextureObjectByTarget(textureUploadTarget, textureTarget);
if (!textureObject) return; if (!textureObject) return;
THROW_UNIMPL_EXCEPTION; SetTextureBorderColorFromFloats(textureObject, params);
break; break;
} }
case GL_TEXTURE_SWIZZLE_RGBA: { case GL_TEXTURE_SWIZZLE_RGBA: {
@@ -401,8 +416,7 @@ namespace MobileGL::MG_Impl::GLImpl {
// ======================= Processing ================================ // ======================= Processing ================================
auto& textureObject = GetTextureObjectByTarget(textureUploadTarget, textureTarget); auto& textureObject = GetTextureObjectByTarget(textureUploadTarget, textureTarget);
if (!textureObject) return; if (!textureObject) return;
SetTextureBorderColorFromInts(textureObject, params);
THROW_UNIMPL_EXCEPTION;
break; break;
} }
case GL_TEXTURE_SWIZZLE_RGBA: { case GL_TEXTURE_SWIZZLE_RGBA: {
@@ -436,7 +450,11 @@ namespace MobileGL::MG_Impl::GLImpl {
void TexParameterIiv_State(GLenum target, GLenum pname, const GLint* params) { void TexParameterIiv_State(GLenum target, GLenum pname, const GLint* params) {
switch (pname) { switch (pname) {
case GL_TEXTURE_BORDER_COLOR: { case GL_TEXTURE_BORDER_COLOR: {
THROW_UNIMPL_EXCEPTION; TextureUploadTarget textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
auto& textureObject = GetTextureObjectByTarget(textureUploadTarget, textureTarget);
if (!textureObject) return;
SetTextureBorderColorFromInts(textureObject, params);
break; break;
} }
case GL_TEXTURE_SWIZZLE_RGBA: { case GL_TEXTURE_SWIZZLE_RGBA: {
@@ -470,7 +488,12 @@ namespace MobileGL::MG_Impl::GLImpl {
void TexParameterIuiv_State(GLenum target, GLenum pname, const GLuint* params) { void TexParameterIuiv_State(GLenum target, GLenum pname, const GLuint* params) {
switch (pname) { switch (pname) {
case GL_TEXTURE_BORDER_COLOR: { case GL_TEXTURE_BORDER_COLOR: {
THROW_UNIMPL_EXCEPTION; TextureUploadTarget textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
auto& textureObject = GetTextureObjectByTarget(textureUploadTarget, textureTarget);
if (!textureObject) return;
textureObject->SetBorderColor(FloatVec4(static_cast<Float>(params[0]), static_cast<Float>(params[1]),
static_cast<Float>(params[2]), static_cast<Float>(params[3])));
break; break;
} }
case GL_TEXTURE_SWIZZLE_RGBA: { case GL_TEXTURE_SWIZZLE_RGBA: {
@@ -806,13 +829,17 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
void GetTexParameterIuiv_State(GLenum target, GLenum pname, GLuint* params) { void GetTexParameterIuiv_State(GLenum target, GLenum pname, GLuint* params) {
// TODO: implement if (params == nullptr) return;
THROW_UNIMPL_EXCEPTION;
GLint signedParams[4] = {0, 0, 0, 0};
GetTexParameteriv_State(target, pname, signedParams);
for (int i = 0; i < 4; ++i) {
params[i] = static_cast<GLuint>(signedParams[i]);
}
} }
void GetTexParameterIiv_State(GLenum target, GLenum pname, GLint* params) { void GetTexParameterIiv_State(GLenum target, GLenum pname, GLint* params) {
// TODO: implement GetTexParameteriv_State(target, pname, params);
THROW_UNIMPL_EXCEPTION;
} }
void GetTexParameteriv_State(GLenum target, GLenum pname, GLint* params) { void GetTexParameteriv_State(GLenum target, GLenum pname, GLint* params) {
@@ -855,9 +882,48 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
break; break;
case GL_TEXTURE_BASE_LEVEL: case GL_TEXTURE_BASE_LEVEL:
if (params) {
*params = static_cast<GLint>(textureObject->GetLevelRange().x());
}
break;
case GL_TEXTURE_MAX_LEVEL: case GL_TEXTURE_MAX_LEVEL:
if (params) {
*params = static_cast<GLint>(textureObject->GetLevelRange().y());
}
break;
case GL_TEXTURE_BORDER_COLOR: case GL_TEXTURE_BORDER_COLOR:
break; // TODO if (params) {
const auto& borderColor = textureObject->GetBorderColor();
params[0] = static_cast<GLint>(borderColor.x());
params[1] = static_cast<GLint>(borderColor.y());
params[2] = static_cast<GLint>(borderColor.z());
params[3] = static_cast<GLint>(borderColor.w());
}
break;
case GL_TEXTURE_SWIZZLE_R:
if (params) {
*params = static_cast<GLint>(
MG_Util::ConvertTextureSwizzleParamToGLEnum(textureObject->GetSwizzleParam(TextureSwizzleParam::Red)));
}
break;
case GL_TEXTURE_SWIZZLE_G:
if (params) {
*params = static_cast<GLint>(MG_Util::ConvertTextureSwizzleParamToGLEnum(
textureObject->GetSwizzleParam(TextureSwizzleParam::Green)));
}
break;
case GL_TEXTURE_SWIZZLE_B:
if (params) {
*params = static_cast<GLint>(
MG_Util::ConvertTextureSwizzleParamToGLEnum(textureObject->GetSwizzleParam(TextureSwizzleParam::Blue)));
}
break;
case GL_TEXTURE_SWIZZLE_A:
if (params) {
*params = static_cast<GLint>(MG_Util::ConvertTextureSwizzleParamToGLEnum(
textureObject->GetSwizzleParam(TextureSwizzleParam::Alpha)));
}
break;
case GL_TEXTURE_WRAP_S: case GL_TEXTURE_WRAP_S:
if (params) { if (params) {
*params = (GLint)MG_Util::ConvertSamplerWrapModeToGLEnum(textureObject->GetSamplerObject()->GetWrapS()); *params = (GLint)MG_Util::ConvertSamplerWrapModeToGLEnum(textureObject->GetSamplerObject()->GetWrapS());
@@ -933,14 +999,50 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
break; break;
case GL_TEXTURE_BASE_LEVEL: case GL_TEXTURE_BASE_LEVEL:
if (params) {
*params = static_cast<GLfloat>(textureObject->GetLevelRange().x());
}
break;
case GL_TEXTURE_MAX_LEVEL: case GL_TEXTURE_MAX_LEVEL:
if (params) {
*params = static_cast<GLfloat>(textureObject->GetLevelRange().y());
}
break;
case GL_TEXTURE_SWIZZLE_R: case GL_TEXTURE_SWIZZLE_R:
if (params) {
*params = static_cast<GLfloat>(
MG_Util::ConvertTextureSwizzleParamToGLEnum(textureObject->GetSwizzleParam(TextureSwizzleParam::Red)));
}
break;
case GL_TEXTURE_SWIZZLE_G: case GL_TEXTURE_SWIZZLE_G:
if (params) {
*params = static_cast<GLfloat>(MG_Util::ConvertTextureSwizzleParamToGLEnum(
textureObject->GetSwizzleParam(TextureSwizzleParam::Green)));
}
break;
case GL_TEXTURE_SWIZZLE_B: case GL_TEXTURE_SWIZZLE_B:
if (params) {
*params = static_cast<GLfloat>(MG_Util::ConvertTextureSwizzleParamToGLEnum(
textureObject->GetSwizzleParam(TextureSwizzleParam::Blue)));
}
break;
case GL_TEXTURE_SWIZZLE_A: case GL_TEXTURE_SWIZZLE_A:
if (params) {
*params = static_cast<GLfloat>(MG_Util::ConvertTextureSwizzleParamToGLEnum(
textureObject->GetSwizzleParam(TextureSwizzleParam::Alpha)));
}
break;
case GL_TEXTURE_SWIZZLE_RGBA: case GL_TEXTURE_SWIZZLE_RGBA:
case GL_TEXTURE_BORDER_COLOR:
break; // TODO break; // TODO
case GL_TEXTURE_BORDER_COLOR:
if (params) {
const auto& borderColor = textureObject->GetBorderColor();
params[0] = borderColor.x();
params[1] = borderColor.y();
params[2] = borderColor.z();
params[3] = borderColor.w();
}
break;
case GL_TEXTURE_WRAP_S: case GL_TEXTURE_WRAP_S:
if (params) { if (params) {
*params = *params =
@@ -1386,7 +1488,7 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
// Add to GL_Texture.cpp // Add to GL_Texture.cpp
void GetTexImage_State(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels) { Bool GetTexImage_State(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels) {
// ======================= Converting ================================ // ======================= Converting ================================
TextureUploadTarget textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target); TextureUploadTarget textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
@@ -1399,7 +1501,7 @@ namespace MobileGL::MG_Impl::GLImpl {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", "Invalid texture target")); MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", "Invalid texture target"));
return; return false;
} }
// Validate level // Validate level
@@ -1407,7 +1509,7 @@ namespace MobileGL::MG_Impl::GLImpl {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", "Level must be non-negative")); MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", "Level must be non-negative"));
return; return false;
} }
// Validate format // Validate format
@@ -1415,7 +1517,7 @@ namespace MobileGL::MG_Impl::GLImpl {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", "Invalid format")); MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", "Invalid format"));
return; return false;
} }
// Validate type // Validate type
@@ -1423,7 +1525,7 @@ namespace MobileGL::MG_Impl::GLImpl {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", "Invalid pixel data type")); MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", "Invalid pixel data type"));
return; return false;
} }
// Get texture object // Get texture object
@@ -1438,7 +1540,7 @@ namespace MobileGL::MG_Impl::GLImpl {
MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation, MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State",
"No valid texture bound to target")); "No valid texture bound to target"));
return; return false;
} }
// Check texture completeness // Check texture completeness
@@ -1446,7 +1548,7 @@ namespace MobileGL::MG_Impl::GLImpl {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", "Texture is incomplete")); MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", "Texture is incomplete"));
return; return false;
} }
// Check PBO state // Check PBO state
@@ -1459,7 +1561,7 @@ namespace MobileGL::MG_Impl::GLImpl {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", ErrorCode::InvalidOperation, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State",
"Pixel pack buffer is currently mapped")); "Pixel pack buffer is currently mapped"));
return; return false;
} }
// Check alignment // Check alignment
@@ -1469,7 +1571,7 @@ namespace MobileGL::MG_Impl::GLImpl {
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State",
"Pixel data not aligned for pixel pack buffer")); "Pixel data not aligned for pixel pack buffer"));
return; return false;
} }
} }
@@ -1482,21 +1584,11 @@ namespace MobileGL::MG_Impl::GLImpl {
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State",
"No stencil buffer for stencil index format")); "No stencil buffer for stencil index format"));
return; return false;
} }
} }
// Check for multisampling return true;
if (textureObject->GetStorageType() == TextureStorageType::Mipmap) {
auto mipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
if (mipmapObject->GetMipmapLevelCount() > 1) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State",
"Multisampled textures not supported for GetTexImage"));
return;
}
}
} }
/* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */ /* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */
@@ -1538,9 +1630,6 @@ namespace MobileGL::MG_Impl::GLImpl {
textureObject = MG_State::pGLContext->GetTextureObject(texture); textureObject = MG_State::pGLContext->GetTextureObject(texture);
} }
MG_State::pGLContext->GetImageTextureBinding(static_cast<Int>(unit))
.Bind(textureObject, level, layered, layer, access, format);
auto bindImageTexture = MG_Backend::gBackendFunctionsTable.GL.BindImageTexture; auto bindImageTexture = MG_Backend::gBackendFunctionsTable.GL.BindImageTexture;
if (!bindImageTexture) { if (!bindImageTexture) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
@@ -1549,6 +1638,9 @@ namespace MobileGL::MG_Impl::GLImpl {
"Backend does not support image texture binding.")); "Backend does not support image texture binding."));
return; return;
} }
MG_State::pGLContext->GetImageTextureBinding(static_cast<Int>(unit))
.Bind(textureObject, level, layered, layer, access, format);
bindImageTexture(unit, texture, level, layered, layer, access, format); bindImageTexture(unit, texture, level, layered, layer, access, format);
} }
@@ -1557,7 +1649,7 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
void GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels) { void GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels) {
GetTexImage_State(target, level, format, type, pixels); if (!GetTexImage_State(target, level, format, type, pixels)) return;
GetTexImage_Backend(target, level, format, type, pixels); GetTexImage_Backend(target, level, format, type, pixels);
} }
@@ -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];
obj = MakeShared<MG_State::GLState::TextureObject2D>(0); 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);
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;
} }
@@ -11,8 +11,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
void DisableVertexAttribArray_State(GLuint index) { void DisableVertexAttribArray_State(GLuint index) {
if (!VertexArrayImpl::ValidateVertexAttributeIndex(index)) return; if (!VertexArrayImpl::ValidateVertexAttributeIndex(index)) return;
@@ -163,6 +219,287 @@ 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]);
}
void VertexAttribDivisor(GLuint index, GLuint divisor) { void VertexAttribDivisor(GLuint index, GLuint divisor) {
VertexAttribDivisor_State(index, divisor); VertexAttribDivisor_State(index, divisor);
} }
@@ -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 VertexAttribDivisor(GLuint index, GLuint divisor); void VertexAttribDivisor(GLuint index, GLuint divisor);
GLboolean IsVertexArray(GLuint array); GLboolean IsVertexArray(GLuint array);
void DisableVertexAttribArray(GLuint index); void DisableVertexAttribArray(GLuint index);
+1
View File
@@ -35,6 +35,7 @@ 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::BackLeft, 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);
@@ -120,10 +120,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);
@@ -148,6 +151,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;
if (access & BufferMappingAccessBit::Write) { if (access & BufferMappingAccessBit::Write) {
m_stagingData.resize(range.end - range.start); m_stagingData.resize(range.end - range.start);
@@ -162,14 +172,6 @@ namespace MobileGL::MG_State::GLState {
m_ownsStagingData = false; m_ownsStagingData = false;
return m_dataPtr->data() + range.start; return m_dataPtr->data() + range.start;
} }
m_change.Bits |=
!(access & BufferMappingAccessBit::InvalidateBuffer || access & BufferMappingAccessBit::InvalidateRange)
? BufferChangeBits::ForbidInvalidationBit
: BufferChangeBits::None;
m_change.Bits |= !(access & BufferMappingAccessBit::Unsynchronized)
? BufferChangeBits::ForbidUnsynchronizationBit
: BufferChangeBits::None;
} }
const SharedPtr<Data>& BufferObject::GetDataReadOnly() const { const SharedPtr<Data>& BufferObject::GetDataReadOnly() const {
@@ -209,6 +211,18 @@ namespace MobileGL::MG_State::GLState {
return m_isMapped ? m_mappedRange : Range1D{0, 0}; return m_isMapped ? m_mappedRange : Range1D{0, 0};
} }
void* BufferObject::GetMappedPointer() {
if (!m_isMapped) {
return nullptr;
}
if (m_ownsStagingData) {
return m_stagingData.data();
}
return m_dataPtr->data() + m_mappedRange.start;
}
Flags<BufferMappingAccessBit> BufferObject::GetMappingAccess() const { Flags<BufferMappingAccessBit> BufferObject::GetMappingAccess() const {
return m_isMapped ? m_mappingAccess : BufferMappingAccessBit::Null; return m_isMapped ? m_mappingAccess : BufferMappingAccessBit::Null;
} }
@@ -94,6 +94,7 @@ namespace MobileGL {
SizeT GetSize() const; SizeT GetSize() const;
BufferUsage GetUsage() const; BufferUsage GetUsage() const;
Range1D GetMappedRange() const; Range1D GetMappedRange() const;
void* GetMappedPointer();
const SharedPtr<Data>& GetDataReadOnly() const; const SharedPtr<Data>& GetDataReadOnly() const;
Flags<BufferMappingAccessBit> GetMappingAccess() const; Flags<BufferMappingAccessBit> GetMappingAccess() const;
Uint GetExternalIndex() const; Uint GetExternalIndex() const;
@@ -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);
+92 -3
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);
} }
@@ -381,9 +434,45 @@ namespace MobileGL::MG_State {
m_renderState.SetClearStencil(stencil); m_renderState.SetClearStencil(stencil);
} }
Uint32 GLContext::GetClearStencil() const { Uint32 GLContext::GetClearStencil() const {
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 {
@@ -136,7 +140,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)); }
@@ -107,6 +141,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 +163,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 +185,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 +219,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,
@@ -155,12 +196,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;
@@ -174,6 +230,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;
@@ -181,7 +243,26 @@ namespace MobileGL {
FrontFaceMode FrontFaceModeSetting = FrontFaceMode::CounterClockwise; FrontFaceMode FrontFaceModeSetting = FrontFaceMode::CounterClockwise;
// 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
}; };
@@ -197,6 +278,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);
@@ -216,12 +304,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);
@@ -234,6 +329,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;
@@ -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;
} }
@@ -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);
@@ -48,11 +48,14 @@ namespace MobileGL::MG_Util::BackendLoader {
return false; return false;
} }
Bool allRequiredLoaded = true;
#define INIT_GLES_FUNC(name) \ #define INIT_GLES_FUNC(name) \
do { \ do { \
funcs.name = (MG_External::GLES::name##_PTR)procAddress(#name); \ funcs.name = (MG_External::GLES::name##_PTR)procAddress(#name); \
if (!funcs.name) { \ if (!funcs.name) { \
MGLOG_E("Failed to load GLES function: %s", #name); \ MGLOG_E("Failed to load GLES function: %s", #name); \
allRequiredLoaded = false; \
} \ } \
} while (0); } while (0);
@@ -149,6 +152,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,7 +433,7 @@ namespace MobileGL::MG_Util::BackendLoader {
INIT_GLES_FUNC(glMultiDrawElementsIndirectEXT) INIT_GLES_FUNC(glMultiDrawElementsIndirectEXT)
INIT_GLES_FUNC(glMultiDrawElementsBaseVertexEXT) INIT_GLES_FUNC(glMultiDrawElementsBaseVertexEXT)
} }
return true; return allRequiredLoaded;
} }
Bool AcquireEGLFunctions(MG_External::EGLFunctionsTable& funcs) { Bool AcquireEGLFunctions(MG_External::EGLFunctionsTable& funcs) {
@@ -438,11 +443,15 @@ namespace MobileGL::MG_Util::BackendLoader {
MGLOG_E("Failed to open libEGL.so"); MGLOG_E("Failed to open libEGL.so");
return false; return false;
} }
Bool allRequiredLoaded = true;
#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); \
if (!funcs.name) { \ if (!funcs.name) { \
MGLOG_E("Failed to load EGL function: %s", #name); \ MGLOG_E("Failed to load EGL function: %s", #name); \
allRequiredLoaded = false; \
} \ } \
} while (0); } while (0);
@@ -495,7 +504,7 @@ namespace MobileGL::MG_Util::BackendLoader {
INIT_EGL_FUNC(eglGetPlatformDisplay) INIT_EGL_FUNC(eglGetPlatformDisplay)
INIT_EGL_FUNC(eglWaitSync) INIT_EGL_FUNC(eglWaitSync)
} }
return true; return allRequiredLoaded;
} }
Bool FillInGLESCapabilities(MG_External::GLESCapabilities& caps, const MG_External::GLESFunctionsTable& glesFuncs) { Bool FillInGLESCapabilities(MG_External::GLESCapabilities& caps, const MG_External::GLESFunctionsTable& glesFuncs) {
@@ -535,6 +544,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,6 +1019,53 @@ 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
@@ -15,6 +15,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) {
@@ -83,6 +106,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;
return true; return true;
} }
@@ -93,5 +167,53 @@ 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;
} }
} // namespace MobileGL::MG_Util::BackendLoader } // namespace MobileGL::MG_Util::BackendLoader
@@ -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;
}; };
} // namespace MG_External } // namespace MG_External
namespace MG_Util::BackendLoader { namespace MG_Util::BackendLoader {
@@ -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:
@@ -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:
@@ -72,6 +72,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, ";
@@ -84,7 +88,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:
@@ -200,6 +200,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());
@@ -70,7 +70,7 @@ namespace MobileGL {
class SpvcSession { class SpvcSession {
public: public:
SpvcSession() {} SpvcSession() = default;
explicit SpvcSession(const Vector<unsigned int>& spirv, explicit SpvcSession(const Vector<unsigned int>& spirv,
Flags<SessionUsageBit> usage); Flags<SessionUsageBit> usage);
@@ -97,7 +97,7 @@ namespace MobileGL {
spvc_result ParseMetaData(); spvc_result ParseMetaData();
private: private:
Flags<SessionUsageBit> usage; Flags<SessionUsageBit> usage{};
// SPIRV-Cross state (used when Transpile flag is set) // SPIRV-Cross state (used when Transpile flag is set)
spvc_context context = nullptr; spvc_context context = nullptr;
@@ -154,8 +154,8 @@ namespace MobileGL::MG_Util::PixelStoreProcessor {
MGLOG_D("%s: Swizzle (BGRA)", __func__); MGLOG_D("%s: Swizzle (BGRA)", __func__);
// MGLOG_D("%s: pixel0 before = %x", __func__, *((Uint32*)layerDst)); // MGLOG_D("%s: pixel0 before = %x", __func__, *((Uint32*)layerDst));
ProcessColorSwizzle(layerDst, static_cast<SizeT>(copyWidth), ProcessColorSwizzle(layerDst, static_cast<SizeT>(copyWidth),
{TextureSwizzleParam::Green, TextureSwizzleParam::Blue, {TextureSwizzleParam::Blue, TextureSwizzleParam::Green,
TextureSwizzleParam::Alpha, TextureSwizzleParam::Red}); TextureSwizzleParam::Red, TextureSwizzleParam::Alpha});
// MGLOG_D("%s: pixel0 after = %x", __func__, *((Uint32*)layerDst)); // MGLOG_D("%s: pixel0 after = %x", __func__, *((Uint32*)layerDst));
} }
// else // else
@@ -157,6 +157,9 @@ namespace MobileGL::MG_Util::TextureFormatProcessor {
case GL_SRGB8: case GL_SRGB8:
*outFormat = GL_RGB; *outFormat = GL_RGB;
break; break;
case GL_SRGB8_ALPHA8:
*outFormat = GL_RGBA;
break;
// Color sized other // Color sized other
case GL_RGB9_E5: case GL_RGB9_E5:
@@ -178,6 +181,7 @@ namespace MobileGL::MG_Util::TextureFormatProcessor {
break; break;
// Depth Stencil // Depth Stencil
case GL_DEPTH24_STENCIL8:
case GL_DEPTH32F_STENCIL8: case GL_DEPTH32F_STENCIL8:
case GL_DEPTH_STENCIL: case GL_DEPTH_STENCIL:
*outFormat = GL_DEPTH_STENCIL; *outFormat = GL_DEPTH_STENCIL;
@@ -298,6 +302,9 @@ namespace MobileGL::MG_Util::TextureFormatProcessor {
case GL_SRGB8: case GL_SRGB8:
*outType = GL_UNSIGNED_BYTE; *outType = GL_UNSIGNED_BYTE;
break; break;
case GL_SRGB8_ALPHA8:
*outType = GL_UNSIGNED_BYTE;
break;
// Color sized other // Color sized other
case GL_RGB9_E5: case GL_RGB9_E5:
@@ -331,6 +338,9 @@ namespace MobileGL::MG_Util::TextureFormatProcessor {
break; break;
// Depth Stencil // Depth Stencil
case GL_DEPTH24_STENCIL8:
*outType = GL_UNSIGNED_INT_24_8;
break;
case GL_DEPTH32F_STENCIL8: case GL_DEPTH32F_STENCIL8:
case GL_DEPTH_STENCIL: case GL_DEPTH_STENCIL:
*outType = GL_FLOAT_32_UNSIGNED_INT_24_8_REV; *outType = GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
+1 -1
View File
@@ -115,7 +115,7 @@ namespace MobileGL {
// represents a range of [start, end) // represents a range of [start, end)
struct Range1D { struct Range1D {
SizeT start = 0; SizeT start = 0;
SizeT end = ~0u; SizeT end = ~SizeT(0);
void Update(SizeT newStart, SizeT newEnd) { void Update(SizeT newStart, SizeT newEnd) {
MOBILEGL_ASSERT(newStart <= newEnd, "Range1D::Update: newStart (%zu) > newEnd (%zu)", newStart, newEnd); MOBILEGL_ASSERT(newStart <= newEnd, "Range1D::Update: newStart (%zu) > newEnd (%zu)", newStart, newEnd);
+826
View File
File diff suppressed because one or more lines are too long