mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-07 19:58:32 +09:00
[Fix] (MG_Impl, MG_State, MG_Backend, MG_Util): Do source audit by Codex.
This commit is contained in:
@@ -15,7 +15,16 @@
|
||||
#include <MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h>
|
||||
|
||||
namespace MobileGL {
|
||||
namespace {
|
||||
Bool g_isInitialized = false;
|
||||
}
|
||||
|
||||
void Initialize() {
|
||||
if (g_isInitialized) {
|
||||
MGLOG_D("MobileGL already initialized; skipping duplicate Initialize()");
|
||||
return;
|
||||
}
|
||||
|
||||
MG_Util::Debug::InitFile();
|
||||
MGLOG_I("Initializing MobileGL...");
|
||||
MG_ConfigLoader::Init();
|
||||
@@ -28,16 +37,24 @@ namespace MobileGL {
|
||||
MGLOG_D("MG_Impl initialized");
|
||||
glslang::InitializeProcess();
|
||||
MGLOG_D("glslang initialized");
|
||||
g_isInitialized = true;
|
||||
MGLOG_I("MobileGL initialized");
|
||||
}
|
||||
|
||||
void Destroy() {
|
||||
if (!g_isInitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
MGLOG_I("MobileGL closing...");
|
||||
glslang::FinalizeProcess();
|
||||
MG_Backend::pActiveBackendObject.reset();
|
||||
MG_State::pGLContext.reset();
|
||||
MG_State::pEGLContext.reset();
|
||||
MG_Impl::GLImpl::TextureImpl::pProxyTextureManager.reset();
|
||||
MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo.reset();
|
||||
MG_Backend::gBackendFunctionsTable = {};
|
||||
g_isInitialized = false;
|
||||
MG_Util::Debug::Close();
|
||||
|
||||
// TODO: add and use Destroy functions for other subsystems
|
||||
|
||||
@@ -90,6 +90,54 @@ namespace MobileGL {
|
||||
|
||||
struct DynamicBackendParameters {
|
||||
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 {
|
||||
|
||||
@@ -97,6 +97,21 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
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) {
|
||||
return DirectGLES::InitPbufferSurface(width, height);
|
||||
}
|
||||
@@ -214,6 +229,55 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
|
||||
void BackendObject_DirectGLES::UpdateDynamicBackendParameters() {
|
||||
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 {
|
||||
|
||||
@@ -21,6 +21,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
Bool InitWindowSurface() override;
|
||||
Bool InitializeEGLDisplay(EGLDisplay dpy, EGLint* major, EGLint* minor) 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 SwapEGLBuffers(EGLDisplay dpy, EGLSurface draw) override;
|
||||
void ReleaseEGLResources() override;
|
||||
|
||||
@@ -415,7 +415,16 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
} \
|
||||
}
|
||||
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(StencilTest, GL_STENCIL_TEST);
|
||||
SYNC_CAPABILITY(CullFace, GL_CULL_FACE);
|
||||
|
||||
#undef SYNC_CAPABILITY
|
||||
@@ -528,6 +537,34 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
if (parameters.DepthMask != g_syncedRenderStateParameters.DepthMask) {
|
||||
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
|
||||
@@ -546,6 +583,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
if (parameters.ClearDepth != g_syncedRenderStateParameters.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
|
||||
@@ -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_syncedRenderStateParameters = parameters;
|
||||
g_hasSyncedRenderState = true;
|
||||
|
||||
@@ -614,10 +614,27 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
MG_Util::ConvertGLEnumToString(err).c_str());
|
||||
});
|
||||
auto texelSize = textureMipmapObject->GetMipmapTexelSize(uploadTarget, level);
|
||||
g_GLESFuncs.glTexSubImage2D(glUploadTarget, static_cast<GLint>(level), 0, 0,
|
||||
static_cast<GLsizei>(texelSize.x()),
|
||||
static_cast<GLsizei>(texelSize.y()), glFormat, glType,
|
||||
textureMipmapObject->MapMipmapData(uploadTarget, level));
|
||||
const void* mipData = textureMipmapObject->MapMipmapData(uploadTarget, level);
|
||||
switch (stateTextureObject->GetTarget()) {
|
||||
case TextureTarget::Texture2D:
|
||||
case TextureTarget::TextureCubeMap:
|
||||
g_GLESFuncs.glTexSubImage2D(glUploadTarget, static_cast<GLint>(level), 0, 0,
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -912,7 +929,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
return false;
|
||||
}
|
||||
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);
|
||||
g_GLESFuncs.glFramebufferTexture2D(glFBOTarget, glBackendAttachment, glTextureTarget,
|
||||
backendTextureObject->GetBackendTextureId(),
|
||||
@@ -1428,7 +1449,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
stateRBOObject->GetExternalIndex());
|
||||
|
||||
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.",
|
||||
stateRBOObject->GetExternalIndex());
|
||||
return;
|
||||
@@ -1440,15 +1462,23 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
TextureInternalFormat internalFormat = stateRBOObject->GetInternalFormat();
|
||||
Int width = static_cast<Int>(stateRBOObject->GetWidth());
|
||||
Int height = static_cast<Int>(stateRBOObject->GetHeight());
|
||||
Int samples = static_cast<Int>(stateRBOObject->GetSamples());
|
||||
GLenum glInternalFormat, glType, glFormat;
|
||||
TextureImpl::GenerateTextureFormatInfo(internalFormat, &glInternalFormat, &glFormat, &glType);
|
||||
|
||||
g_GLESFuncs.glRenderbufferStorage(GL_RENDERBUFFER, glInternalFormat, static_cast<GLsizei>(width),
|
||||
static_cast<GLsizei>(height));
|
||||
if (samples > 0) {
|
||||
g_GLESFuncs.glRenderbufferStorageMultisample(
|
||||
GL_RENDERBUFFER, static_cast<GLsizei>(samples), glInternalFormat, static_cast<GLsizei>(width),
|
||||
static_cast<GLsizei>(height));
|
||||
} else {
|
||||
g_GLESFuncs.glRenderbufferStorage(GL_RENDERBUFFER, glInternalFormat, static_cast<GLsizei>(width),
|
||||
static_cast<GLsizei>(height));
|
||||
}
|
||||
|
||||
m_cacheInternalFormat = internalFormat;
|
||||
m_cacheWidth = width;
|
||||
m_cacheHeight = height;
|
||||
m_cacheSamples = samples;
|
||||
|
||||
m_isInitialized = true;
|
||||
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;
|
||||
Int m_cacheWidth = 0;
|
||||
Int m_cacheHeight = 0;
|
||||
Int m_cacheSamples = 0;
|
||||
};
|
||||
|
||||
extern StateBackendObjectRegistry<MG_State::GLState::RenderbufferObject, BackendRenderbufferObject>
|
||||
|
||||
@@ -149,7 +149,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
#ifdef TRACY_ENABLE
|
||||
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
|
||||
#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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,5 +207,53 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
void BackendObject_DirectVulkan::UpdateDynamicBackendParameters() {
|
||||
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
|
||||
|
||||
@@ -188,18 +188,18 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return packet;
|
||||
}
|
||||
|
||||
FrameContext::PresentInfoPacket FrameContext::GetPresentInfo(VkSwapchainKHR swapchain, const Uint32& imageIndex) const {
|
||||
FrameContext::PresentInfoPacket FrameContext::GetPresentInfo(VkSwapchainKHR swapchain, Uint32 imageIndex) const {
|
||||
AssertValidSwapchainImageIndex(imageIndex);
|
||||
PresentInfoPacket packet{};
|
||||
packet.waitSemaphore = m_swapchainImageRenderFinishedSemaphores[imageIndex];
|
||||
packet.swapchain = swapchain;
|
||||
packet.imageIndex = &imageIndex;
|
||||
packet.imageIndex = imageIndex;
|
||||
|
||||
packet.presentInfo.waitSemaphoreCount = 1;
|
||||
packet.presentInfo.pWaitSemaphores = &packet.waitSemaphore;
|
||||
packet.presentInfo.swapchainCount = 1;
|
||||
packet.presentInfo.pSwapchains = &packet.swapchain;
|
||||
packet.presentInfo.pImageIndices = packet.imageIndex;
|
||||
packet.presentInfo.pImageIndices = &packet.imageIndex;
|
||||
packet.presentInfo.pResults = nullptr;
|
||||
return packet;
|
||||
}
|
||||
@@ -212,13 +212,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = vkResetFences(device, 1, &frame.imageInFlightFence);
|
||||
result = vkAcquireNextImageKHR(device, swapchain, timeout, frame.imageAvailableSemaphore, acquireFence,
|
||||
&outImageIndex);
|
||||
if (result != VK_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return vkAcquireNextImageKHR(device, swapchain, timeout, frame.imageAvailableSemaphore, acquireFence,
|
||||
&outImageIndex);
|
||||
return vkResetFences(device, 1, &frame.imageInFlightFence);
|
||||
}
|
||||
|
||||
Uint32 FrameContext::GetCurrentFrameIndex() const {
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
struct PresentInfoPacket {
|
||||
VkSemaphore waitSemaphore = VK_NULL_HANDLE;
|
||||
VkSwapchainKHR swapchain = VK_NULL_HANDLE;
|
||||
const Uint32* imageIndex = nullptr;
|
||||
Uint32 imageIndex = 0;
|
||||
VkPresentInfoKHR presentInfo{VK_STRUCTURE_TYPE_PRESENT_INFO_KHR};
|
||||
};
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
Bool TransitionToPresent(VkImage image, VkImageLayout oldLayout,
|
||||
VkImageLayout presentLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||
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,
|
||||
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.depthTestEnable, sizeof(payload.depthTestEnable)));
|
||||
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.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) {
|
||||
XXHASH_VERIFY(XXH64_update(
|
||||
m_hashState,
|
||||
@@ -86,7 +104,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
static constexpr VkDynamicState kDynamicStates[] = {
|
||||
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{};
|
||||
@@ -105,6 +129,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
raster.polygonMode = VK_POLYGON_MODE_FILL;
|
||||
raster.cullMode = payload.cullMode;
|
||||
raster.frontFace = payload.frontFace;
|
||||
raster.depthBiasEnable = payload.depthBiasEnable ? VK_TRUE : VK_FALSE;
|
||||
raster.rasterizerDiscardEnable = payload.rasterizerDiscardEnable ? VK_TRUE : VK_FALSE;
|
||||
raster.lineWidth = 1.0f;
|
||||
|
||||
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.depthCompareOp = payload.depthCompareOp;
|
||||
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);
|
||||
for (Uint32 i = 0; i < payload.colorAttachmentCount; ++i) {
|
||||
colorAttachments[i] = payload.colorBlendAttachments[i];
|
||||
}
|
||||
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.pAttachments = colorAttachments.empty() ? nullptr : colorAttachments.data();
|
||||
|
||||
|
||||
@@ -32,7 +32,20 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
VkFrontFace frontFace = VK_FRONT_FACE_CLOCKWISE;
|
||||
Bool depthTestEnable = false;
|
||||
Bool depthWriteEnable = false;
|
||||
Bool depthBiasEnable = false;
|
||||
Bool rasterizerDiscardEnable = false;
|
||||
Bool logicOpEnable = false;
|
||||
Bool stencilTestEnable = false;
|
||||
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{};
|
||||
const Vector<VkPipelineShaderStageCreateInfo>* stages = nullptr;
|
||||
const VkPipelineVertexInputStateCreateInfo* vertexInputState = nullptr;
|
||||
|
||||
@@ -153,7 +153,10 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
MGLOG_I("Picked present mode: %s", string_VkPresentModeKHR(presentMode));
|
||||
|
||||
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("Swapchain currentTransform = %s",
|
||||
string_VkSurfaceTransformFlagBitsKHR(swapchainCaps.currentTransform));
|
||||
@@ -234,11 +237,16 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
// Properly initialize Default FBO here
|
||||
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());
|
||||
colorTex->AllocateStorage(
|
||||
TextureUploadTarget::Texture2D, 0, {
|
||||
{(Int)createInfo.imageExtent.width, (Int)createInfo.imageExtent.height, 1},
|
||||
createInfo.imageExtent.width * (Int)createInfo.imageExtent.height * 4}); // TODO: 4 is format size
|
||||
{extentWidth, extentHeight, 1},
|
||||
defaultAttachmentByteSize}); // TODO: 4 is format size
|
||||
TextureInternalFormat depthFormat = TextureInternalFormat::Depth24Stencil8;
|
||||
switch (m_depthStencilFormat) {
|
||||
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());
|
||||
depthTex->SetInternalFormat(depthFormat);
|
||||
depthTex->AllocateStorage(TextureUploadTarget::Texture2D, 0, {
|
||||
{(Int)createInfo.imageExtent.width, (Int)createInfo.imageExtent.height, 1},
|
||||
createInfo.imageExtent.width * createInfo.imageExtent.width * 4}); // TODO: 4 is format size
|
||||
{extentWidth, extentHeight, 1},
|
||||
defaultAttachmentByteSize}); // TODO: 4 is format size
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,19 @@
|
||||
#include "MG_Util/Converters/MGToStr/TextureEnumConverter.h"
|
||||
|
||||
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) {
|
||||
if (attachmentType == FramebufferAttachmentType::None) {
|
||||
return nullptr;
|
||||
@@ -23,7 +35,30 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
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() {
|
||||
@@ -40,46 +75,46 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
auto& drawbufs = drawFbo.GetDrawBuffers();
|
||||
// This should automatically work on default & offscreen FBO
|
||||
for (auto drawbuf: drawbufs) {
|
||||
auto texture = GetClearableAttachmentTexture(drawFbo, drawbuf);
|
||||
if (!texture) {
|
||||
const auto* attachment = GetClearableAttachment(drawFbo, drawbuf);
|
||||
if (!attachment) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QueueClear({
|
||||
.mask = GL_COLOR_BUFFER_BIT,
|
||||
.color = clearPayload.color
|
||||
}, texture);
|
||||
}, *attachment);
|
||||
|
||||
MGLOG_D("%s: %s (texture %d) - color = (%.2f, %.2f, %.2f, %.2f)", __func__,
|
||||
MG_Util::ConvertFramebufferAttachmentTypeToString(drawbuf).c_str(),
|
||||
texture->GetExternalIndex(),
|
||||
attachment->GetTexture()->GetExternalIndex(),
|
||||
clearPayload.color[0], clearPayload.color[1], clearPayload.color[2], clearPayload.color[3]);
|
||||
}
|
||||
}
|
||||
|
||||
if (mask & GL_DEPTH_BUFFER_BIT) {
|
||||
auto texture = GetClearableAttachmentTexture(drawFbo, FramebufferAttachmentType::Depth);
|
||||
if (texture) {
|
||||
const auto* attachment = GetClearableAttachment(drawFbo, FramebufferAttachmentType::Depth);
|
||||
if (attachment) {
|
||||
QueueClear({
|
||||
.mask = GL_DEPTH_BUFFER_BIT,
|
||||
.depth = clearPayload.depth,
|
||||
}, texture);
|
||||
}, *attachment);
|
||||
|
||||
MGLOG_D("%s: Depth (texture %d) - depth = (%.2f)", __func__,
|
||||
texture->GetExternalIndex(), clearPayload.depth);
|
||||
attachment->GetTexture()->GetExternalIndex(), clearPayload.depth);
|
||||
}
|
||||
}
|
||||
|
||||
if (mask & GL_STENCIL_BUFFER_BIT) {
|
||||
auto texture = GetClearableAttachmentTexture(drawFbo, FramebufferAttachmentType::Stencil);
|
||||
if (texture) {
|
||||
const auto* attachment = GetClearableAttachment(drawFbo, FramebufferAttachmentType::Stencil);
|
||||
if (attachment) {
|
||||
QueueClear({
|
||||
.mask = GL_STENCIL_BUFFER_BIT,
|
||||
.stencil = clearPayload.stencil,
|
||||
}, texture);
|
||||
}, *attachment);
|
||||
|
||||
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;
|
||||
auto* pTexture = weakTexturePtr.lock().get();
|
||||
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;
|
||||
if (clearPayload.mask & GL_COLOR_BUFFER_BIT) {
|
||||
pending.color = clearPayload.color;
|
||||
@@ -108,20 +171,40 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
|
||||
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) {
|
||||
if (m_aliveObjects.find(texture) == m_aliveObjects.end() ||
|
||||
m_pendingClears.find(texture) == m_pendingClears.end()) {
|
||||
MGLOG_D("%s: Failed getting pending clear for texture %d", __func__, texture->GetExternalIndex());
|
||||
Bool VkClearManager::HasPendingClear(const PendingClearKey& key) {
|
||||
return key.texture != nullptr && m_pendingClears.find(key) != m_pendingClears.end();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
outPayload = m_pendingClears[texture];
|
||||
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__,
|
||||
texture->GetExternalIndex(),
|
||||
MG_Util::ConvertTextureInternalFormatToString(texture->GetFormat()).c_str(),
|
||||
outPayload = it->second;
|
||||
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__,
|
||||
key.texture->GetExternalIndex(),
|
||||
MG_Util::ConvertTextureInternalFormatToString(key.texture->GetFormat()).c_str(),
|
||||
key.mipLevel, key.baseArrayLayer, key.layerCount,
|
||||
static_cast<Uint32>(outPayload.mask),
|
||||
outPayload.color[0], outPayload.color[1], outPayload.color[2], outPayload.color[3],
|
||||
outPayload.depth,
|
||||
@@ -129,10 +212,59 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
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) {
|
||||
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_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() {
|
||||
@@ -145,7 +277,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
for (auto it = m_aliveObjects.begin(); it != m_aliveObjects.end();) {
|
||||
auto current = it++;
|
||||
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);
|
||||
++count;
|
||||
}
|
||||
|
||||
@@ -29,8 +29,43 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
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 {
|
||||
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();
|
||||
void Shutdown();
|
||||
|
||||
@@ -38,13 +73,22 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
void QueueClear(
|
||||
const ClearAttachmentPayload& clearPayload,
|
||||
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 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(const PendingClearKey& key);
|
||||
void PopPendingClear(const MG_State::GLState::FramebufferAttachmentObject& attachment);
|
||||
SizeT CollectGarbage();
|
||||
private:
|
||||
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;
|
||||
};
|
||||
} // namespace MobileGL::MG_Backend::DirectVulkan
|
||||
|
||||
@@ -22,6 +22,32 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
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(
|
||||
const MG_State::GLState::FramebufferObject& fbo,
|
||||
FramebufferAttachmentType attachmentType,
|
||||
@@ -79,6 +105,10 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
|
||||
void VkRenderPassManager::Shutdown() {
|
||||
m_renderPasses.clear();
|
||||
RenderPassEntry::s_textureResourcesScratch.clear();
|
||||
s_activeRenderPass = {};
|
||||
s_hasActiveRenderPass = false;
|
||||
}
|
||||
|
||||
VkRenderPassManager::HashType VkRenderPassManager::ComputeHash(
|
||||
@@ -117,6 +147,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
if (att.IsTexture()) {
|
||||
const Int textureLevel = att.GetTextureLevel();
|
||||
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;
|
||||
auto* texture = att.GetTexture().get();
|
||||
@@ -129,11 +161,12 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
if (includePendingClear && att.IsTexture()) {
|
||||
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)));
|
||||
if (hasClear) {
|
||||
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)));
|
||||
if (hasPayload) {
|
||||
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);
|
||||
if (att.IsTexture() && m_clearManager.HasPendingClear(att.GetTexture().get())) {
|
||||
if (att.IsTexture() && m_clearManager.HasPendingClear(att)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -266,7 +299,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
texture2d->GetFormat());
|
||||
desc.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
ClearAttachmentPayload clearPayload{};
|
||||
Bool hasClear = m_clearManager.GetPendingClear(texture, clearPayload);
|
||||
Bool hasClear = m_clearManager.GetPendingClear(att, clearPayload);
|
||||
VkImageLayout trackedColorLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
desc.loadOp = hasClear ?
|
||||
VK_ATTACHMENT_LOAD_OP_CLEAR :
|
||||
@@ -280,7 +313,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
if (hasClear) {
|
||||
pendingClearAttachments.emplace_back(PendingClearAttachmentInfo {
|
||||
.attachmentIndex = attachmentIndex,
|
||||
.texture = texture
|
||||
.key = VkClearManager::MakePendingClearKey(att)
|
||||
});
|
||||
}
|
||||
if (width == 0)
|
||||
@@ -313,7 +346,12 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
.textureMipLevel = attachmentMipLevel,
|
||||
.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,
|
||||
"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;
|
||||
}
|
||||
|
||||
// Depth attachment description
|
||||
// Depth/stencil attachment description
|
||||
auto& depthAtt = fbo.GetAttachment(FramebufferAttachmentType::Depth);
|
||||
auto& stencilAtt = fbo.GetAttachment(FramebufferAttachmentType::Stencil);
|
||||
VkAttachmentDescription depthAttachmentDescription;
|
||||
VkAttachmentReference depthAttachmentRef;
|
||||
depthAttachmentRef.attachment = VK_ATTACHMENT_UNUSED;
|
||||
depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
VkTextureManager::TextureResource* depthTextureResource = nullptr;
|
||||
if (depthAtt.IsComplete() && depthAtt.IsTexture()) {
|
||||
auto& texture = *depthAtt.GetTexture();
|
||||
const Uint32 attachmentMipLevel = static_cast<Uint32>(std::max(depthAtt.GetTextureLevel(), 0));
|
||||
const auto isUsableDepthStencilAttachment = [](const auto& attachment) {
|
||||
return attachment.IsComplete() && attachment.IsTexture();
|
||||
};
|
||||
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());
|
||||
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 clearStencil = hasClear && (clearPayload.mask & GL_STENCIL_BUFFER_BIT) != 0;
|
||||
VkImageLayout trackedDepthLayout = isDefaultFbo ?
|
||||
@@ -396,7 +450,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
if (hasClear) {
|
||||
pendingClearAttachments.emplace_back(PendingClearAttachmentInfo {
|
||||
.attachmentIndex = depthAttachmentIndex,
|
||||
.texture = &texture
|
||||
.key = VkClearManager::MakePendingClearKey(*selectedDepthStencilAttachment)
|
||||
});
|
||||
}
|
||||
if (isDefaultFbo) {
|
||||
@@ -417,12 +471,18 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
.finalLayout = depthAttachmentDescription.finalLayout,
|
||||
});
|
||||
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,
|
||||
"GetOrCreateRenderPass: GetOrCreateAttachmentView failed at depth attachment");
|
||||
if (width == 0 || height == 0) {
|
||||
width = depthAtt.GetSize().x();
|
||||
height = depthAtt.GetSize().y();
|
||||
width = selectedDepthStencilAttachment->GetSize().x();
|
||||
height = selectedDepthStencilAttachment->GetSize().y();
|
||||
}
|
||||
}
|
||||
attachmentDescriptions.emplace_back(depthAttachmentDescription);
|
||||
@@ -439,7 +499,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
subpassDesc.colorAttachmentCount = colorAttachmentRefs.size();
|
||||
subpassDesc.pColorAttachments = colorAttachmentRefs.data();
|
||||
subpassDesc.pResolveAttachments = nullptr;
|
||||
subpassDesc.pDepthStencilAttachment = depthAtt.IsComplete() ? &depthAttachmentRef : VK_NULL_HANDLE;
|
||||
subpassDesc.pDepthStencilAttachment = hasDepthStencilAttachment ? &depthAttachmentRef : VK_NULL_HANDLE;
|
||||
subpassDesc.preserveAttachmentCount = 0;
|
||||
subpassDesc.pPreserveAttachments = nullptr;
|
||||
|
||||
@@ -512,11 +572,11 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
clearValue.depthStencil = {1.0f, 0};
|
||||
}
|
||||
for (const auto& pending: renderPassEntry.pendingClearAttachments) {
|
||||
if (!pending.texture || pending.attachmentIndex >= clearValues.size()) {
|
||||
if (pending.key.texture == nullptr || pending.attachmentIndex >= clearValues.size()) {
|
||||
continue;
|
||||
}
|
||||
ClearAttachmentPayload clearPayload{};
|
||||
if (!s_clearManager->GetPendingClear(pending.texture, clearPayload)) {
|
||||
if (!s_clearManager->GetPendingClear(pending.key, clearPayload)) {
|
||||
continue;
|
||||
}
|
||||
if ((clearPayload.mask & GL_COLOR_BUFFER_BIT) != 0) {
|
||||
@@ -524,7 +584,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
clearPayload.color.x(),
|
||||
clearPayload.color.y(),
|
||||
clearPayload.color.z(),
|
||||
ResolveColorClearAlpha(pending.texture, clearPayload.color.w())
|
||||
ResolveColorClearAlpha(pending.key.texture, clearPayload.color.w())
|
||||
};
|
||||
}
|
||||
if ((clearPayload.mask & GL_DEPTH_BUFFER_BIT) != 0) {
|
||||
@@ -540,7 +600,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
for (const auto& pending: renderPassEntry.pendingClearAttachments) {
|
||||
s_clearManager->PopPendingClear(pending.texture);
|
||||
s_clearManager->PopPendingClear(pending.key);
|
||||
}
|
||||
s_activeRenderPass.hash = renderPassEntry.hash;
|
||||
s_activeRenderPass.compatibilityHash = renderPassEntry.compatibilityHash;
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
struct PendingClearAttachmentInfo {
|
||||
Uint32 attachmentIndex = 0;
|
||||
MG_State::GLState::ITextureObject* texture = nullptr;
|
||||
PendingClearKey key{};
|
||||
};
|
||||
|
||||
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,
|
||||
VkPipelineStageFlags& outSrcStageMask,
|
||||
VkAccessFlags& outSrcAccessMask) {
|
||||
@@ -594,7 +600,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
|
||||
perMipView = CreateImageView(resource->image, resource->format, resource->aspect, resource->viewType,
|
||||
mipLevel, 1, resource->arrayLayers);
|
||||
mipLevel, 1, 0, resource->arrayLayers);
|
||||
if (perMipView == VK_NULL_HANDLE) {
|
||||
MGLOG_D("%s: CreateImageView failed for textureId=%d mipLevel=%u", __func__, texture.GetExternalIndex(), mipLevel);
|
||||
return VK_NULL_HANDLE;
|
||||
@@ -603,6 +609,53 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
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,
|
||||
Uint32 mipLevel) {
|
||||
TextureResource* resource = SyncTextureAndGetDescriptor(texture);
|
||||
@@ -622,7 +675,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
const TextureFormatInfo formatInfo = ResolveTextureFormatInfo(texture.GetFormat());
|
||||
const VkComponentMapping sampledComponents = ResolveSampledViewComponents(texture, formatInfo);
|
||||
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) {
|
||||
MGLOG_D("%s: CreateImageView failed for textureId=%d mipLevel=%u", __func__, texture.GetExternalIndex(),
|
||||
mipLevel);
|
||||
@@ -1109,7 +1162,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
const TextureFormatInfo formatInfo = ResolveTextureFormatInfo(texture.GetFormat());
|
||||
const VkComponentMapping sampledComponents = ResolveSampledViewComponents(texture, formatInfo);
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
@@ -1122,6 +1175,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
VkImageView VkTextureManager::CreateImageView(VkImage image, VkFormat format, VkImageAspectFlags aspect,
|
||||
VkImageViewType viewType, Uint32 baseMipLevel, Uint32 levelCount,
|
||||
Uint32 baseArrayLayer,
|
||||
Uint32 layerCount,
|
||||
const VkComponentMapping* components) const {
|
||||
VkImageViewCreateInfo viewInfo{};
|
||||
@@ -1136,7 +1190,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
viewInfo.subresourceRange.aspectMask = aspect;
|
||||
viewInfo.subresourceRange.baseMipLevel = baseMipLevel;
|
||||
viewInfo.subresourceRange.levelCount = levelCount;
|
||||
viewInfo.subresourceRange.baseArrayLayer = 0;
|
||||
viewInfo.subresourceRange.baseArrayLayer = baseArrayLayer;
|
||||
viewInfo.subresourceRange.layerCount = layerCount;
|
||||
|
||||
VkImageView view = VK_NULL_HANDLE;
|
||||
@@ -1293,17 +1347,18 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
1, ©);
|
||||
}
|
||||
|
||||
const VkImageLayout finalLayout = ResolveSampledReadOnlyLayout(aspectMask);
|
||||
VkImageLayout uploadLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
ok = TransitionImageLayout(commandBuffer, outResource.image,
|
||||
uploadLayout,
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
kGraphicsSampledReadStages,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
VK_ACCESS_SHADER_READ_BIT,
|
||||
aspectMask, 0, outResource.mipLevels, outResource.arrayLayers);
|
||||
MOBILEGL_ASSERT(ok, "TransitionImageLayout to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL failed");
|
||||
outResource.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
uploadLayout,
|
||||
finalLayout,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
kGraphicsSampledReadStages,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
VK_ACCESS_SHADER_READ_BIT,
|
||||
aspectMask, 0, outResource.mipLevels, outResource.arrayLayers);
|
||||
MOBILEGL_ASSERT(ok, "TransitionImageLayout to sampled read-only layout failed");
|
||||
outResource.layout = finalLayout;
|
||||
|
||||
VK_VERIFY(vkEndCommandBuffer(commandBuffer), "vkEndCommandBuffer(texture)");
|
||||
|
||||
@@ -1331,7 +1386,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
for (const auto& item : uploadItems) {
|
||||
mipmapTexture.MarkStorageDirty(item.target, item.level, false);
|
||||
}
|
||||
outResource.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
outResource.layout = finalLayout;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,11 +30,37 @@ public:
|
||||
};
|
||||
|
||||
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;
|
||||
VmaAllocation allocation = nullptr;
|
||||
VkImageView fullView = VK_NULL_HANDLE;
|
||||
Vector<VkImageView> perMipViews;
|
||||
Vector<VkImageView> perMipSampledViews;
|
||||
UnorderedMap<AttachmentViewKey, VkImageView, AttachmentViewKeyHash> attachmentViews;
|
||||
VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
VkExtent2D extent = {0, 0};
|
||||
Uint32 depth = 1;
|
||||
@@ -55,6 +81,7 @@ public:
|
||||
std::swap(this->fullView, that.fullView);
|
||||
std::swap(this->perMipViews, that.perMipViews);
|
||||
std::swap(this->perMipSampledViews, that.perMipSampledViews);
|
||||
std::swap(this->attachmentViews, that.attachmentViews);
|
||||
std::swap(this->layout, that.layout);
|
||||
std::swap(this->extent, that.extent);
|
||||
std::swap(this->depth, that.depth);
|
||||
@@ -82,12 +109,18 @@ public:
|
||||
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) {
|
||||
vmaDestroyImage(s_allocator, image, allocation);
|
||||
}
|
||||
fullView = VK_NULL_HANDLE;
|
||||
perMipViews.clear();
|
||||
perMipSampledViews.clear();
|
||||
attachmentViews.clear();
|
||||
image = VK_NULL_HANDLE;
|
||||
allocation = nullptr;
|
||||
layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
@@ -118,6 +151,9 @@ public:
|
||||
TextureResource* SyncTextureAndGetDescriptor(
|
||||
MG_State::GLState::ITextureObject& texture);
|
||||
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);
|
||||
void UpdateTrackedImageLayout(MG_State::GLState::ITextureObject* texture, VkImageLayout newLayout);
|
||||
void UpdateTrackedImageLayoutAfterAttachmentWrite(VkCommandBuffer commandBuffer,
|
||||
@@ -146,6 +182,7 @@ private:
|
||||
Bool SyncTextureViews(const MG_State::GLState::ITextureObject& texture, TextureResource& resource);
|
||||
VkImageView CreateImageView(VkImage image, VkFormat format, VkImageAspectFlags aspect,
|
||||
VkImageViewType viewType, Uint32 baseMipLevel, Uint32 levelCount,
|
||||
Uint32 baseArrayLayer,
|
||||
Uint32 layerCount,
|
||||
const VkComponentMapping* components = nullptr) const;
|
||||
Bool UploadDirtyMipLevels(MG_State::GLState::TextureObjectMipmap &mipmapTexture,
|
||||
|
||||
@@ -90,6 +90,78 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
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 {
|
||||
Unknown,
|
||||
FloatLike,
|
||||
@@ -632,6 +704,51 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
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) {
|
||||
switch (layout) {
|
||||
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
|
||||
@@ -778,6 +895,19 @@ void main() {
|
||||
: 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 {
|
||||
Identity = 0,
|
||||
Rotate90 = 1,
|
||||
@@ -792,6 +922,8 @@ void main() {
|
||||
IntVec2 extent = {0, 0};
|
||||
Uint32 mipLevel = 0;
|
||||
Uint32 mipLevelCount = 1;
|
||||
Uint32 baseArrayLayer = 0;
|
||||
Uint32 layerCount = 1;
|
||||
const char* label = nullptr;
|
||||
};
|
||||
|
||||
@@ -968,6 +1100,8 @@ void main() {
|
||||
outBinding.extent = {static_cast<Int>(extent.width), static_cast<Int>(extent.height)};
|
||||
outBinding.mipLevel = 0;
|
||||
outBinding.mipLevelCount = 1;
|
||||
outBinding.baseArrayLayer = 0;
|
||||
outBinding.layerCount = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -990,6 +1124,8 @@ void main() {
|
||||
outBinding.extent = {attachmentExtent.x(), attachmentExtent.y()};
|
||||
outBinding.mipLevel = static_cast<Uint32>(std::max(attachment.GetTextureLevel(), 0));
|
||||
outBinding.mipLevelCount = resource->mipLevels;
|
||||
outBinding.baseArrayLayer = ResolveAttachmentBaseArrayLayer(attachment);
|
||||
outBinding.layerCount = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1013,6 +1149,8 @@ void main() {
|
||||
outBinding.extent = {static_cast<Int>(extent.width), static_cast<Int>(extent.height)};
|
||||
outBinding.mipLevel = 0;
|
||||
outBinding.mipLevelCount = 1;
|
||||
outBinding.baseArrayLayer = 0;
|
||||
outBinding.layerCount = 1;
|
||||
outBinding.trackedLayout = nullptr;
|
||||
if ((requiredAspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != 0) {
|
||||
outBinding.image = swapchainObject.GetImage(swapchainImageIndex);
|
||||
@@ -1067,6 +1205,8 @@ void main() {
|
||||
outBinding.extent = {attachmentExtent.x(), attachmentExtent.y()};
|
||||
outBinding.mipLevel = static_cast<Uint32>(std::max(attachment.GetTextureLevel(), 0));
|
||||
outBinding.mipLevelCount = resource->mipLevels;
|
||||
outBinding.baseArrayLayer = ResolveAttachmentBaseArrayLayer(attachment);
|
||||
outBinding.layerCount = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1099,6 +1239,8 @@ void main() {
|
||||
static_cast<Int>(std::max(1u, resource->extent.height >> mipLevel))};
|
||||
outBinding.mipLevel = mipLevel;
|
||||
outBinding.mipLevelCount = 1;
|
||||
outBinding.baseArrayLayer = 0;
|
||||
outBinding.layerCount = 1;
|
||||
outBinding.label = "destination texture";
|
||||
return true;
|
||||
}
|
||||
@@ -1123,6 +1265,8 @@ void main() {
|
||||
outBinding.extent = {static_cast<Int>(extent.width), static_cast<Int>(extent.height)};
|
||||
outBinding.mipLevel = 0;
|
||||
outBinding.mipLevelCount = 1;
|
||||
outBinding.baseArrayLayer = 0;
|
||||
outBinding.layerCount = 1;
|
||||
outBinding.trackedLayout = nullptr;
|
||||
if ((requiredAspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != 0) {
|
||||
outBinding.image = swapchainObject.GetImage(swapchainImageIndex);
|
||||
@@ -1179,6 +1323,8 @@ void main() {
|
||||
outBinding.extent = {attachmentExtent.x(), attachmentExtent.y()};
|
||||
outBinding.mipLevel = static_cast<Uint32>(std::max(attachment.GetTextureLevel(), 0));
|
||||
outBinding.mipLevelCount = 1;
|
||||
outBinding.baseArrayLayer = ResolveAttachmentBaseArrayLayer(attachment);
|
||||
outBinding.layerCount = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2166,14 +2312,7 @@ void main() {
|
||||
|
||||
vkCmdBeginRenderPass(frame.commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
|
||||
VkViewport viewport{};
|
||||
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);
|
||||
ApplyGLViewportState(frame.commandBuffer, dstTexelSize.xy());
|
||||
|
||||
VkRect2D scissor{};
|
||||
scissor.offset = {0, 0};
|
||||
@@ -2345,6 +2484,16 @@ void main() {
|
||||
}
|
||||
auto cullFaceEnabled = MG_State::pGLContext->IsCapabilityEnabled(CapabilityInput::CullFace);
|
||||
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();
|
||||
const auto colorWriteMask = static_cast<VkColorComponentFlags>(
|
||||
(mask.r() ? VK_COLOR_COMPONENT_R_BIT : 0u) |
|
||||
@@ -2366,19 +2515,52 @@ void main() {
|
||||
.frontFace = VK_FRONT_FACE_CLOCKWISE,
|
||||
.depthTestEnable = depthTestEnabled,
|
||||
.depthWriteEnable = depthTestEnabled && MG_State::pGLContext->GetDepthMask(),
|
||||
.depthBiasEnable = polygonOffsetFillEnabled,
|
||||
.rasterizerDiscardEnable = rasterizerDiscardEnabled,
|
||||
.logicOpEnable = colorLogicOpEnabled,
|
||||
.stencilTestEnable = stencilTestEnabled,
|
||||
.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,
|
||||
.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;
|
||||
if (!hasDepthStencilAttachment && (payload.depthTestEnable || payload.depthWriteEnable)) {
|
||||
MGLOG_D("GetOrCreatePipeline: disabling depth test/write for program=%u because render pass has no depth attachment (attachmentCount=%u colorAttachmentCount=%u)",
|
||||
if (!hasDepthStencilAttachment &&
|
||||
(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(),
|
||||
renderPassEntry.attachmentCount,
|
||||
renderPassEntry.colorAttachmentCount);
|
||||
payload.depthTestEnable = false;
|
||||
payload.depthWriteEnable = false;
|
||||
payload.stencilTestEnable = false;
|
||||
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;
|
||||
MOBILEGL_ASSERT(
|
||||
@@ -2555,6 +2737,10 @@ void main() {
|
||||
m_textureManager->CollectGarbage();
|
||||
const auto& drawFbo =
|
||||
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& program = *MG_State::pGLContext->GetCurrentProgram();
|
||||
ProgramFactory::CompileOptionFlags transformFlags = GetShaderTransformFlags(m_swapchainObject.GetPreTransform());
|
||||
@@ -2686,14 +2872,11 @@ void main() {
|
||||
MOBILEGL_ASSERT(idxUploadOk, "SetupDraw skipped: failed to upload index buffer");
|
||||
}
|
||||
|
||||
VkViewport viewport{};
|
||||
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);
|
||||
ApplyGLViewportState(frame.commandBuffer, renderPassEntry->extent);
|
||||
ApplyBlendConstants(frame.commandBuffer);
|
||||
ApplyPolygonOffsetState(frame.commandBuffer);
|
||||
ApplyLineWidthState(frame.commandBuffer);
|
||||
ApplyStencilState(frame.commandBuffer);
|
||||
|
||||
Bool scissorEnabled = MG_State::pGLContext->IsCapabilityEnabled(CapabilityInput::ScissorTest);
|
||||
VkRect2D scissor{};
|
||||
@@ -2780,6 +2963,10 @@ void main() {
|
||||
m_clearManager->CollectGarbage();
|
||||
auto* fbo = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject().get();
|
||||
MOBILEGL_ASSERT(fbo, "VulkanRenderer::Clear: draw framebuffer not found (fbo == nullptr)");
|
||||
if (IsUnsupportedFramebufferForDirectVulkan(*fbo)) {
|
||||
RecordUnsupportedFramebufferError(__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
ClearFramebufferPayload payload {
|
||||
.color = MG_State::pGLContext->GetClearColor(),
|
||||
@@ -2794,6 +2981,10 @@ void main() {
|
||||
m_clearManager->CollectGarbage();
|
||||
auto* fbo = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject().get();
|
||||
MOBILEGL_ASSERT(fbo, "VulkanRenderer::QueueClearBufferPayload: draw framebuffer not found");
|
||||
if (IsUnsupportedFramebufferForDirectVulkan(*fbo)) {
|
||||
RecordUnsupportedFramebufferError(__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
auto queueAttachmentClear = [&](FramebufferAttachmentType attachmentType) {
|
||||
if (attachmentType == FramebufferAttachmentType::None) {
|
||||
@@ -2803,11 +2994,7 @@ void main() {
|
||||
if (!attachment.IsTexture() || attachment.IsRenderbuffer()) {
|
||||
return;
|
||||
}
|
||||
auto texture = attachment.GetTexture();
|
||||
if (!texture) {
|
||||
return;
|
||||
}
|
||||
m_clearManager->QueueClear(clearPayload, texture);
|
||||
m_clearManager->QueueClear(clearPayload, attachment);
|
||||
};
|
||||
|
||||
switch (buffer) {
|
||||
@@ -2920,8 +3107,8 @@ void main() {
|
||||
|
||||
Bool VulkanRenderer::MaterializePendingClearForTexture(VkCommandBuffer commandBuffer,
|
||||
MG_State::GLState::ITextureObject& texture) {
|
||||
ClearAttachmentPayload clearPayload{};
|
||||
if (!m_clearManager->GetPendingClear(&texture, clearPayload)) {
|
||||
Vector<PendingClearEntry> pendingClears;
|
||||
if (!m_clearManager->GetPendingClears(&texture, pendingClears)) {
|
||||
return true;
|
||||
}
|
||||
MOBILEGL_ASSERT(VkRenderPassManager::GetActiveRenderPass() == nullptr,
|
||||
@@ -2940,53 +3127,65 @@ void main() {
|
||||
Bool ok = VkTextureManager::TransitionImageLayout(
|
||||
commandBuffer, resource->image, resource->layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
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,
|
||||
"MaterializePendingClearForTexture: failed to transition textureId=%d to TRANSFER_DST",
|
||||
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;
|
||||
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;
|
||||
for (const auto& pendingClear : pendingClears) {
|
||||
MOBILEGL_ASSERT(pendingClear.key.mipLevel < resource->mipLevels,
|
||||
"MaterializePendingClearForTexture: textureId=%d pending clear mip=%u out of range %u",
|
||||
texture.GetExternalIndex(), pendingClear.key.mipLevel, resource->mipLevels);
|
||||
MOBILEGL_ASSERT(pendingClear.key.baseArrayLayer + pendingClear.key.layerCount <= resource->arrayLayers,
|
||||
"MaterializePendingClearForTexture: textureId=%d pending clear layer span [%u, %u) exceeds arrayLayers=%u",
|
||||
texture.GetExternalIndex(), pendingClear.key.baseArrayLayer,
|
||||
pendingClear.key.baseArrayLayer + pendingClear.key.layerCount, resource->arrayLayers);
|
||||
|
||||
VkImageSubresourceRange subresourceRange{};
|
||||
subresourceRange.baseMipLevel = pendingClear.key.mipLevel;
|
||||
subresourceRange.levelCount = 1;
|
||||
subresourceRange.baseArrayLayer = pendingClear.key.baseArrayLayer;
|
||||
subresourceRange.layerCount = pendingClear.key.layerCount;
|
||||
|
||||
const auto& clearPayload = pendingClear.payload;
|
||||
if ((resource->aspect & VK_IMAGE_ASPECT_COLOR_BIT) != 0) {
|
||||
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(
|
||||
commandBuffer, resource->image, clearLayout, sampledLayout,
|
||||
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,
|
||||
"MaterializePendingClearForTexture: failed to transition textureId=%d to sampled layout",
|
||||
texture.GetExternalIndex());
|
||||
@@ -3054,14 +3253,7 @@ void main() {
|
||||
const Bool ok = VkRenderPassManager::BeginRenderPass(frame.commandBuffer, renderPassEntry);
|
||||
MOBILEGL_ASSERT(ok, "%s: BeginRenderPass failed", __func__);
|
||||
|
||||
VkViewport viewport{};
|
||||
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);
|
||||
ApplyGLViewportState(frame.commandBuffer, renderPassEntry.extent);
|
||||
|
||||
VkRect2D scissor{};
|
||||
scissor.offset = {0, 0};
|
||||
@@ -3163,6 +3355,11 @@ void main() {
|
||||
auto drawFbo = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
|
||||
MOBILEGL_ASSERT(readFbo != nullptr, "VulkanRenderer::BlitFramebuffer: read 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();
|
||||
if (!frame.isCommandRecording) {
|
||||
@@ -3285,13 +3482,13 @@ void main() {
|
||||
VkImageCopy copyRegion{};
|
||||
copyRegion.srcSubresource.aspectMask = srcBinding.aspectMask;
|
||||
copyRegion.srcSubresource.mipLevel = srcBinding.mipLevel;
|
||||
copyRegion.srcSubresource.baseArrayLayer = 0;
|
||||
copyRegion.srcSubresource.layerCount = 1;
|
||||
copyRegion.srcSubresource.baseArrayLayer = srcBinding.baseArrayLayer;
|
||||
copyRegion.srcSubresource.layerCount = srcBinding.layerCount;
|
||||
copyRegion.srcOffset = {srcX0, srcY0, 0};
|
||||
copyRegion.dstSubresource.aspectMask = dstBinding.aspectMask;
|
||||
copyRegion.dstSubresource.mipLevel = dstBinding.mipLevel;
|
||||
copyRegion.dstSubresource.baseArrayLayer = 0;
|
||||
copyRegion.dstSubresource.layerCount = 1;
|
||||
copyRegion.dstSubresource.baseArrayLayer = dstBinding.baseArrayLayer;
|
||||
copyRegion.dstSubresource.layerCount = dstBinding.layerCount;
|
||||
copyRegion.dstOffset = {dstX0, dstY0, 0};
|
||||
copyRegion.extent = {static_cast<Uint32>(srcWidth), static_cast<Uint32>(srcHeight), 1};
|
||||
|
||||
@@ -3421,14 +3618,14 @@ void main() {
|
||||
VkImageBlit blitRegion{};
|
||||
blitRegion.srcSubresource.aspectMask = srcBinding.aspectMask;
|
||||
blitRegion.srcSubresource.mipLevel = srcBinding.mipLevel;
|
||||
blitRegion.srcSubresource.baseArrayLayer = 0;
|
||||
blitRegion.srcSubresource.layerCount = 1;
|
||||
blitRegion.srcSubresource.baseArrayLayer = srcBinding.baseArrayLayer;
|
||||
blitRegion.srcSubresource.layerCount = srcBinding.layerCount;
|
||||
blitRegion.srcOffsets[0] = {srcX0, srcY0, 0};
|
||||
blitRegion.srcOffsets[1] = {srcX1, srcY1, 1};
|
||||
blitRegion.dstSubresource.aspectMask = dstBinding.aspectMask;
|
||||
blitRegion.dstSubresource.mipLevel = dstBinding.mipLevel;
|
||||
blitRegion.dstSubresource.baseArrayLayer = 0;
|
||||
blitRegion.dstSubresource.layerCount = 1;
|
||||
blitRegion.dstSubresource.baseArrayLayer = dstBinding.baseArrayLayer;
|
||||
blitRegion.dstSubresource.layerCount = dstBinding.layerCount;
|
||||
blitRegion.dstOffsets[0] = {dstX0, dstY0, 0};
|
||||
blitRegion.dstOffsets[1] = {dstX1, dstY1, 1};
|
||||
if (drawIsDefaultFbo) {
|
||||
@@ -3503,6 +3700,11 @@ void main() {
|
||||
"CopyTexSubImage2D requires a framebuffer bound to GL_READ_FRAMEBUFFER.");
|
||||
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();
|
||||
if (!frame.isCommandRecording) {
|
||||
@@ -3601,13 +3803,13 @@ void main() {
|
||||
VkImageCopy copyRegion{};
|
||||
copyRegion.srcSubresource.aspectMask = srcBinding.aspectMask;
|
||||
copyRegion.srcSubresource.mipLevel = srcBinding.mipLevel;
|
||||
copyRegion.srcSubresource.baseArrayLayer = 0;
|
||||
copyRegion.srcSubresource.layerCount = 1;
|
||||
copyRegion.srcSubresource.baseArrayLayer = srcBinding.baseArrayLayer;
|
||||
copyRegion.srcSubresource.layerCount = srcBinding.layerCount;
|
||||
copyRegion.srcOffset = {x, y, 0};
|
||||
copyRegion.dstSubresource.aspectMask = dstBinding.aspectMask;
|
||||
copyRegion.dstSubresource.mipLevel = dstBinding.mipLevel;
|
||||
copyRegion.dstSubresource.baseArrayLayer = 0;
|
||||
copyRegion.dstSubresource.layerCount = 1;
|
||||
copyRegion.dstSubresource.baseArrayLayer = dstBinding.baseArrayLayer;
|
||||
copyRegion.dstSubresource.layerCount = dstBinding.layerCount;
|
||||
copyRegion.dstOffset = {xoffset, yoffset, 0};
|
||||
copyRegion.extent = {static_cast<Uint32>(width), static_cast<Uint32>(height), 1};
|
||||
vkCmdCopyImage(frame.commandBuffer,
|
||||
@@ -4064,7 +4266,8 @@ void main() {
|
||||
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {
|
||||
MGLOG_D("Present, vkAcquireNextImageKHR got %d, recreating swapchain", result);
|
||||
RecreateSwapchain();
|
||||
result = VK_SUCCESS;
|
||||
result =
|
||||
m_frameContext.WaitAndAcquireNextImage(m_device, m_swapchainObject.GetHandle(), m_imageIndexAcquired);
|
||||
}
|
||||
VK_VERIFY(result, "Present, vkAcquireNextImageKHR");
|
||||
CollectDeferredDepthMipmapCleanup(m_frameContext.GetCurrentFrameIndex());
|
||||
@@ -4350,8 +4553,11 @@ void main() {
|
||||
VkPhysicalDeviceFeatures deviceFeatures{};
|
||||
deviceFeatures.geometryShader = supportedDeviceFeatures.geometryShader;
|
||||
deviceFeatures.independentBlend = supportedDeviceFeatures.independentBlend;
|
||||
deviceFeatures.logicOp = supportedDeviceFeatures.logicOp;
|
||||
deviceFeatures.shaderClipDistance = supportedDeviceFeatures.shaderClipDistance;
|
||||
deviceFeatures.shaderCullDistance = supportedDeviceFeatures.shaderCullDistance;
|
||||
deviceFeatures.wideLines = supportedDeviceFeatures.wideLines;
|
||||
m_logicOpFeatureEnabled = deviceFeatures.logicOp == VK_TRUE;
|
||||
|
||||
VkDeviceCreateInfo deviceCreateInfo{};
|
||||
deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||
@@ -4416,16 +4622,20 @@ void main() {
|
||||
|
||||
deviceCreateInfo.enabledExtensionCount = static_cast<Uint32>(enabledDeviceExtensions.size());
|
||||
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.independentBlend ? "true" : "false",
|
||||
supportedDeviceFeatures.logicOp ? "true" : "false",
|
||||
supportedDeviceFeatures.shaderClipDistance ? "true" : "false",
|
||||
supportedDeviceFeatures.shaderCullDistance ? "true" : "false");
|
||||
MGLOG_I("Device feature enabled: geometryShader=%s independentBlend=%s shaderClipDistance=%s shaderCullDistance=%s",
|
||||
supportedDeviceFeatures.shaderCullDistance ? "true" : "false",
|
||||
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.independentBlend ? "true" : "false",
|
||||
deviceFeatures.logicOp ? "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");
|
||||
|
||||
s_vkCmdDrawIndexedIndirectCount = reinterpret_cast<PFNDrawIndexedIndirectCountFunc>(
|
||||
@@ -4726,12 +4936,12 @@ void main() {
|
||||
clearRect.layerCount = 1;
|
||||
|
||||
for (const auto& pending : compatibleRenderPassEntry.pendingClearAttachments) {
|
||||
if (!pending.texture) {
|
||||
if (pending.key.texture == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ClearAttachmentPayload clearPayload{};
|
||||
if (!m_clearManager->GetPendingClear(pending.texture, clearPayload)) {
|
||||
if (!m_clearManager->GetPendingClear(pending.key, clearPayload)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -4744,7 +4954,7 @@ void main() {
|
||||
clearPayload.color.x(),
|
||||
clearPayload.color.y(),
|
||||
clearPayload.color.z(),
|
||||
ResolveColorClearAlpha(pending.texture, clearPayload.color.w())
|
||||
ResolveColorClearAlpha(pending.key.texture, clearPayload.color.w())
|
||||
};
|
||||
} else {
|
||||
if ((clearPayload.mask & GL_DEPTH_BUFFER_BIT) != 0) {
|
||||
@@ -4761,7 +4971,7 @@ void main() {
|
||||
}
|
||||
|
||||
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;
|
||||
Bool m_drawIndirectCountExtensionEnabled = false;
|
||||
Bool m_indexTypeUint8ExtensionEnabled = false;
|
||||
Bool m_logicOpFeatureEnabled = false;
|
||||
using PFNDrawIndexedIndirectCountFunc = void(VKAPI_PTR*)(VkCommandBuffer commandBuffer, VkBuffer buffer,
|
||||
VkDeviceSize offset, VkBuffer countBuffer,
|
||||
VkDeviceSize countBufferOffset, Uint32 maxDrawCount,
|
||||
|
||||
@@ -258,6 +258,9 @@ namespace MobileGL::MG_Impl::EGLImpl {
|
||||
if (!state) {
|
||||
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();
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
if (n < 0) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
@@ -524,16 +611,23 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
BufferTarget bufferTarget = MG_Util::ConvertGLEnumToBufferTarget(target);
|
||||
if (!BufferImpl::ValidateBufferBindingPointTarget(bufferTarget)) return;
|
||||
|
||||
Bool doesBufferObjectCreated = MG_State::pGLContext->ValidateBufferObject(buffer);
|
||||
if (!doesBufferObjectCreated) {
|
||||
MG_State::pGLContext->CreateBufferObject(buffer);
|
||||
SharedPtr<MG_State::GLState::BufferObject> bufferObject;
|
||||
if (buffer != 0) {
|
||||
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);
|
||||
point.Bind(bufferObject);
|
||||
point.SetRange(Range1D(0, bufferObject->GetSize()));
|
||||
MGLOG_D("%s: set range (0, %d)", __func__, bufferObject->GetSize());
|
||||
if (bufferObject) {
|
||||
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) {
|
||||
@@ -542,15 +636,22 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
BufferTarget bufferTarget = MG_Util::ConvertGLEnumToBufferTarget(target);
|
||||
if (!BufferImpl::ValidateBufferBindingPointTarget(bufferTarget)) return;
|
||||
|
||||
Bool doesBufferObjectCreated = MG_State::pGLContext->ValidateBufferObject(buffer);
|
||||
if (!doesBufferObjectCreated) {
|
||||
MG_State::pGLContext->CreateBufferObject(buffer);
|
||||
SharedPtr<MG_State::GLState::BufferObject> bufferObject;
|
||||
if (buffer != 0) {
|
||||
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);
|
||||
point.Bind(bufferObject);
|
||||
point.SetRange(Range1D(offset, offset + size));
|
||||
if (bufferObject) {
|
||||
point.SetRange(Range1D(offset, offset + size));
|
||||
} else {
|
||||
point.ClearRange();
|
||||
}
|
||||
}
|
||||
|
||||
/* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */
|
||||
@@ -558,6 +659,14 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
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) {
|
||||
return IsBuffer_State(buffer);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
namespace MobileGL::MG_Impl::GLImpl {
|
||||
/* @INSERTION_POINT:FUNCTION_DECLARATION@ */
|
||||
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);
|
||||
void DeleteBuffers(GLsizei n, const GLuint* buffers);
|
||||
void FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length);
|
||||
|
||||
@@ -12,6 +12,62 @@
|
||||
#include <MG_Backend/BackendObjects.h>
|
||||
|
||||
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) {
|
||||
#ifdef TRACY_ENABLE
|
||||
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."));
|
||||
return;
|
||||
}
|
||||
if (!ValidateCurrentProgramForCompute(__func__)) return;
|
||||
dispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
|
||||
}
|
||||
|
||||
@@ -176,6 +233,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
"Backend does not support indirect compute dispatch."));
|
||||
return;
|
||||
}
|
||||
if (!ValidateCurrentProgramForCompute(__func__)) return;
|
||||
dispatchComputeIndirect(indirect);
|
||||
}
|
||||
|
||||
@@ -203,74 +261,106 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type,
|
||||
const void* indices, GLint basevertex) {
|
||||
if (!ValidateCurrentProgramForExecution(__func__)) return;
|
||||
if (!ValidatePrimitiveModeForBackend(__func__, mode)) return;
|
||||
DrawRangeElementsBaseVertex_Backend(mode, start, end, count, type, indices, basevertex);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices,
|
||||
GLsizei instancecount, GLint basevertex, GLuint baseinstance) {
|
||||
if (!ValidateCurrentProgramForExecution(__func__)) return;
|
||||
if (!ValidatePrimitiveModeForBackend(__func__, mode)) return;
|
||||
DrawElementsInstancedBaseVertexBaseInstance_Backend(mode, count, type, indices, instancecount, basevertex,
|
||||
baseinstance);
|
||||
}
|
||||
|
||||
void DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type, const void* indices,
|
||||
GLsizei instancecount, GLint basevertex) {
|
||||
if (!ValidateCurrentProgramForExecution(__func__)) return;
|
||||
if (!ValidatePrimitiveModeForBackend(__func__, mode)) return;
|
||||
DrawElementsInstancedBaseVertex_Backend(mode, count, type, indices, instancecount, basevertex);
|
||||
}
|
||||
|
||||
void DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices,
|
||||
GLsizei instancecount, GLuint baseinstance) {
|
||||
if (!ValidateCurrentProgramForExecution(__func__)) return;
|
||||
if (!ValidatePrimitiveModeForBackend(__func__, mode)) return;
|
||||
DrawElementsInstancedBaseInstance_Backend(mode, count, type, indices, instancecount, baseinstance);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void DrawElementsIndirect(GLenum mode, GLenum type, const void* indirect) {
|
||||
if (!ValidateCurrentProgramForExecution(__func__)) return;
|
||||
if (!ValidatePrimitiveModeForBackend(__func__, mode)) return;
|
||||
DrawElementsIndirect_Backend(mode, type, indirect);
|
||||
}
|
||||
|
||||
void DrawArraysInstancedBaseInstance(GLenum mode, GLint first, GLsizei count, GLsizei instancecount,
|
||||
GLuint baseinstance) {
|
||||
if (!ValidateCurrentProgramForExecution(__func__)) return;
|
||||
if (!ValidatePrimitiveModeForBackend(__func__, mode)) return;
|
||||
DrawArraysInstancedBaseInstance_Backend(mode, first, count, instancecount, baseinstance);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void DrawArraysIndirect(GLenum mode, const void* indirect) {
|
||||
if (!ValidateCurrentProgramForExecution(__func__)) return;
|
||||
if (!ValidatePrimitiveModeForBackend(__func__, mode)) return;
|
||||
DrawArraysIndirect_Backend(mode, indirect);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void DrawArrays(GLenum mode, GLint first, GLsizei count) {
|
||||
if (!ValidateCurrentProgramForExecution(__func__)) return;
|
||||
if (!ValidatePrimitiveModeForBackend(__func__, mode)) return;
|
||||
DrawArrays_Backend(mode, first, count);
|
||||
}
|
||||
|
||||
void MultiDrawElements(GLenum mode, const GLsizei* count, GLenum type, const void* const* indices,
|
||||
GLsizei drawcount) {
|
||||
if (!ValidateCurrentProgramForExecution(__func__)) return;
|
||||
if (!ValidatePrimitiveModeForBackend(__func__, mode)) return;
|
||||
MultiDrawElements_Backend(mode, count, type, indices, drawcount);
|
||||
}
|
||||
|
||||
void MultiDrawElementsBaseVertex(GLenum mode, const GLsizei* count, GLenum type, const void* const* indices,
|
||||
GLsizei drawcount, const GLint* basevertex) {
|
||||
if (!ValidateCurrentProgramForExecution(__func__)) return;
|
||||
if (!ValidatePrimitiveModeForBackend(__func__, mode)) return;
|
||||
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) {
|
||||
if (!ValidateCurrentProgramForExecution(__func__)) return;
|
||||
if (!ValidatePrimitiveModeForBackend(__func__, mode)) return;
|
||||
DrawElements_Backend(mode, count, type, indices);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "../RenderState/GL_RenderState.h"
|
||||
#include "../Framebuffer/GL_Framebuffer.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__) {
|
||||
|
||||
@@ -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(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_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, 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)
|
||||
@@ -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, 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_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, 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)
|
||||
@@ -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, 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_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(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, 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)
|
||||
@@ -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, 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_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_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_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, GetVertexAttribfv, GLuint index, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetVertexAttribfv, 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_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(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)
|
||||
@@ -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, 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_STUB_HEAD(void, VertexAttrib1f, GLuint index, GLfloat x) DECLARE_GL_FUNCTION_STUB_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_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_STUB_HEAD(void, VertexAttrib2fv, GLuint index, const GLfloat* v) DECLARE_GL_FUNCTION_STUB_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_STUB_HEAD(void, VertexAttrib3fv, GLuint index, const GLfloat* v) DECLARE_GL_FUNCTION_STUB_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_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, VertexAttrib1f, GLuint index, GLfloat x) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib1f, index, x)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib1fv, GLuint index, const GLfloat* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib1fv, index, v)
|
||||
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_HEAD(void, VertexAttrib2fv, GLuint index, const GLfloat* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib2fv, index, v)
|
||||
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_HEAD(void, VertexAttrib3fv, GLuint index, const GLfloat* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib3fv, index, v)
|
||||
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_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, 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)
|
||||
@@ -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, 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_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_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)
|
||||
@@ -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, 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_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_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_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_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_STUB_HEAD(void, VertexAttribI4iv, GLuint index, const GLint* v) DECLARE_GL_FUNCTION_STUB_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_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, GetVertexAttribIiv, GLuint index, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetVertexAttribIiv, 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_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_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_HEAD(void, VertexAttribI4iv, GLuint index, const GLint* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribI4iv, 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_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_STUB_HEAD(void, Uniform1ui, GLint location, GLuint v0) DECLARE_GL_FUNCTION_STUB_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_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_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_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_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_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_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, Uniform1ui, GLint location, GLuint v0) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform1ui, location, v0)
|
||||
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_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_HEAD(void, Uniform4ui, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform4ui, location, v0, v1, v2, v3)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, Uniform1uiv, GLint location, GLsizei count, const GLuint* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform1uiv, location, count, value)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, Uniform2uiv, GLint location, GLsizei count, const GLuint* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform2uiv, 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_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, 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, 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_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_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)
|
||||
@@ -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, 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_STUB_HEAD(GLsync, FenceSync, GLenum condition, GLbitfield flags) DECLARE_GL_FUNCTION_STUB_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_STUB_HEAD(void, DeleteSync, GLsync sync) DECLARE_GL_FUNCTION_STUB_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_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_STUB_HEAD(void, GetInteger64v, GLenum pname, GLint64* data) DECLARE_GL_FUNCTION_STUB_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(GLsync, FenceSync, GLenum condition, GLbitfield flags) DECLARE_GL_FUNCTION_END(GLsync, FenceSync, condition, flags)
|
||||
DECLARE_GL_FUNCTION_HEAD(GLboolean, IsSync, GLsync sync) DECLARE_GL_FUNCTION_END(GLboolean, IsSync, sync)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, DeleteSync, GLsync sync) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DeleteSync, sync)
|
||||
DECLARE_GL_FUNCTION_HEAD(GLenum, ClientWaitSync, GLsync sync, GLbitfield flags, GLuint64 timeout) DECLARE_GL_FUNCTION_END(GLenum, ClientWaitSync, 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_HEAD(void, GetInteger64v, GLenum pname, GLint64* data) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetInteger64v, pname, data)
|
||||
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_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, 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)
|
||||
@@ -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, 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_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, 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)
|
||||
@@ -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, 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, 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_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, 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_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, 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)
|
||||
@@ -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, 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, 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, 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, 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_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)
|
||||
@@ -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, 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(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, 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, 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)
|
||||
|
||||
@@ -15,10 +15,144 @@
|
||||
#include <MG_State/GLState/ErrorState/Error.h>
|
||||
#include <MG_Util/Converters/GLToStr/GLEnumConverter.h>
|
||||
#include <MG_Util/Converters/GLToMG/TextureEnumConverter.h>
|
||||
#include <MG_Util/Converters/MGToMG/TextureEnumConverter.h>
|
||||
#include <MG_Util/Converters/MGToGL/TextureEnumConverter.h>
|
||||
#include <MG_Util/Converters/MGToStr/TextureEnumConverter.h>
|
||||
#include <MG_Util/Converters/GLToMG/FramebufferEnumConverter.h>
|
||||
|
||||
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,
|
||||
GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
|
||||
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) {
|
||||
// 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,
|
||||
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) {
|
||||
@@ -56,14 +231,15 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
renderbufferObject->AllocateStorage({width, height});
|
||||
renderbufferObject->SetInternalFormat(format);
|
||||
renderbufferObject->SetSamples(0);
|
||||
}
|
||||
|
||||
GLboolean IsRenderbuffer_State(GLuint renderbuffer) {
|
||||
return MG_State::pGLContext->ValidateRenderbufferName(renderbuffer);
|
||||
return MG_State::pGLContext->ValidateRenderbufferObject(renderbuffer);
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -136,6 +312,26 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
: 0;
|
||||
break;
|
||||
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:
|
||||
*params = 0;
|
||||
break;
|
||||
@@ -174,12 +370,31 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
|
||||
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,
|
||||
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) {
|
||||
@@ -199,6 +414,11 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
if (!FramebufferImpl::ValidateFramebufferAttachmentType(attachmentType)) return;
|
||||
if (!FramebufferImpl::ValidateFramebufferTarget(framebufferTarget)) 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& framebufferObject = bindingSlot.GetBoundObject();
|
||||
@@ -224,15 +444,59 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
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) {
|
||||
// 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) {
|
||||
// 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,
|
||||
@@ -246,7 +510,8 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
RenderbufferTarget rbTarget = MG_Util::ConvertGLEnumToRenderbufferTarget(renderbuffertarget);
|
||||
if (!FramebufferImpl::ValidateFramebufferAttachmentType(attachmentType)) 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& framebufferObject = bindingSlot.GetBoundObject();
|
||||
if (!framebufferObject) {
|
||||
@@ -290,6 +555,12 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
// Get bound framebuffer
|
||||
auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw);
|
||||
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);
|
||||
|
||||
static int existenceMap[(SizeT)FramebufferAttachmentType::FramebufferAttachmentTypeCount] = {-1};
|
||||
@@ -308,20 +579,20 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDefaultFBO && attType >= FramebufferAttachmentType::Color0 &&
|
||||
attType <= FramebufferAttachmentType::Color31) {
|
||||
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(
|
||||
"FBO is default FBO, but bufs[{}] = {} is one of the `GL_COLOR_ATTACHMENTn` tokens.", i,
|
||||
MG_Util::ConvertGLEnumToString(bufs[i]))));
|
||||
std::format("FBO is default FBO, but bufs[{}] = {} is not `GL_NONE` or one of the default "
|
||||
"framebuffer color buffer tokens.",
|
||||
i, MG_Util::ConvertGLEnumToString(bufs[i]))));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isDefaultFBO && attType >= FramebufferAttachmentType::FrontLeft &&
|
||||
attType <= FramebufferAttachmentType::BackRight) {
|
||||
if (!isDefaultFBO && attType != FramebufferAttachmentType::None &&
|
||||
(attType < FramebufferAttachmentType::Color0 || attType > FramebufferAttachmentType::Color31)) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidEnum,
|
||||
MakeUnique<GenericErrorInfo>(
|
||||
@@ -388,6 +659,43 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
// Get bound framebuffer
|
||||
auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Read);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -453,24 +761,35 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
|
||||
// TODO: distinguish GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT and GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT
|
||||
// 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
|
||||
return framebufferObject->CheckCompleteness() ? GL_FRAMEBUFFER_COMPLETE
|
||||
: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
|
||||
if (!framebufferObject->CheckCompleteness()) {
|
||||
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) {
|
||||
if (!FramebufferImpl::ValidateRenderbufferName(renderbuffer)) return;
|
||||
if (!FramebufferImpl::ValidateRenderbufferName(renderbuffer, true)) return;
|
||||
RenderbufferTarget renderbufferTarget = MG_Util::ConvertGLEnumToRenderbufferTarget(target);
|
||||
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);
|
||||
if (!doesRenderbufferCreated) {
|
||||
MG_State::pGLContext->CreateRenderbufferObject(renderbuffer);
|
||||
}
|
||||
auto& renderbufferObject = MG_State::pGLContext->GetRenderbufferObject(renderbuffer);
|
||||
|
||||
auto& bindingSlot = MG_State::pGLContext->GetRenderbufferBindingSlot(renderbufferTarget);
|
||||
bindingSlot.Bind(renderbufferObject);
|
||||
}
|
||||
|
||||
@@ -567,7 +886,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
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);
|
||||
TexturePixelDataType texturePixelDataType = MG_Util::ConvertGLEnumToTexturePixelDataType(type);
|
||||
|
||||
@@ -576,7 +895,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
MG_State::pGLContext->RecordError(ErrorCode::InvalidValue,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
|
||||
"Width and height must be non-negative"));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate format
|
||||
@@ -584,7 +903,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidEnum,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", "Invalid format"));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate type
|
||||
@@ -592,7 +911,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidEnum,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", "Invalid pixel data type"));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get bound framebuffer
|
||||
@@ -603,7 +922,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
|
||||
"No framebuffer bound to read target"));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check framebuffer completeness
|
||||
@@ -611,7 +930,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidFramebufferOperation,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", "Framebuffer is incomplete"));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for required buffers
|
||||
@@ -621,7 +940,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
ErrorCode::InvalidOperation,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
|
||||
"No stencil buffer for stencil index format"));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
} else if (textureInputFormat == TextureInputFormat::DepthComponent) {
|
||||
if (!framebufferObject->GetAttachment(FramebufferAttachmentType::Depth).IsValid()) {
|
||||
@@ -629,7 +948,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
ErrorCode::InvalidOperation,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
|
||||
"No depth buffer for depth component format"));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
} else if (textureInputFormat == TextureInputFormat::DepthStencil) {
|
||||
if (!framebufferObject->GetAttachment(FramebufferAttachmentType::Depth).IsValid() ||
|
||||
@@ -638,7 +957,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
ErrorCode::InvalidOperation,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
|
||||
"No depth/stencil buffer for depth-stencil format"));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate type for depth/stencil
|
||||
@@ -647,7 +966,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidEnum, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
|
||||
"Invalid type for depth-stencil format"));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -661,7 +980,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidOperation, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
|
||||
"Pixel pack buffer is currently mapped"));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check alignment
|
||||
@@ -671,7 +990,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
ErrorCode::InvalidOperation,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
|
||||
"Pixel data not aligned for pixel pack buffer"));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -683,9 +1002,11 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
ErrorCode::InvalidOperation,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
|
||||
"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) {
|
||||
@@ -694,7 +1015,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
|
||||
/* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -13,7 +13,10 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
/* @INSERTION_POINT:FUNCTION_DECLARATION@ */
|
||||
const GLubyte* GetString(GLenum name);
|
||||
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 GetInteger64v(GLenum pname, GLint64* params);
|
||||
void GetIntegeri_v(GLenum target, GLuint index, GLint* data);
|
||||
void GetInteger64i_v(GLenum target, GLuint index, GLint64* data);
|
||||
GLenum GetError();
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
#include <MG_Backend/BackendObjects.h>
|
||||
|
||||
namespace MobileGL::MG_Impl::GLImpl {
|
||||
static GLint BoolToGLInt(bool value) {
|
||||
return value ? GL_TRUE : GL_FALSE;
|
||||
}
|
||||
|
||||
static bool CheckShaderNameValidity(Uint shader) {
|
||||
if (shader == 0 || !MG_State::pGLContext->ValidateShaderName(shader)) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
@@ -80,6 +84,16 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
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) {
|
||||
auto& programObject = TryToGetProgramObject(program);
|
||||
if (!programObject) return;
|
||||
@@ -188,9 +202,10 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
std::to_string(program) + "."));
|
||||
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;
|
||||
auto& attribName = programObject->GetAttribName(index);
|
||||
auto& attribName = programObject->GetActiveAttribName(index);
|
||||
CopyStr(bufSize, length, name, attribName.c_str(), (GLsizei)attribName.length());
|
||||
}
|
||||
|
||||
@@ -216,13 +231,38 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
std::to_string(program) + "."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (type != nullptr) *type = programObject->GetUniformType(index);
|
||||
if (size != nullptr) *size = programObject->GetActiveUniformArraySize(index);
|
||||
if (type != nullptr) *type = programObject->GetActiveUniformType(index);
|
||||
if (bufSize == 0) return;
|
||||
auto& uniformName = programObject->GetUniformName(index);
|
||||
auto& uniformName = programObject->GetActiveUniformName(index);
|
||||
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) {
|
||||
if (maxCount < 0) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
@@ -268,7 +308,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
break;
|
||||
case GL_INFO_LOG_LENGTH: {
|
||||
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);
|
||||
break;
|
||||
}
|
||||
@@ -287,7 +327,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params);
|
||||
break;
|
||||
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);
|
||||
break;
|
||||
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);
|
||||
break;
|
||||
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);
|
||||
break;
|
||||
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);
|
||||
break;
|
||||
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);
|
||||
break;
|
||||
case GL_COMPUTE_WORK_GROUP_SIZE: { // GL >= 4.3
|
||||
auto getProgramiv = MG_Backend::gBackendFunctionsTable.GL.GetProgramiv;
|
||||
if (!getProgramiv) {
|
||||
params[0] = 1;
|
||||
params[1] = 1;
|
||||
params[2] = 1;
|
||||
if (!programObject->GetLinkStatus()) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidOperation,
|
||||
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;
|
||||
}
|
||||
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],
|
||||
params[1], params[2]);
|
||||
break;
|
||||
@@ -423,25 +462,13 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
|
||||
// Check if location is valid
|
||||
if (location < 0 || location > programObject->GetMaxUniformLocation()) {
|
||||
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;
|
||||
}
|
||||
|
||||
// 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."));
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -468,12 +495,64 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
// 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) {
|
||||
GetUniform_State(program, location, params);
|
||||
GetUniformScalar_State(program, location, 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) {
|
||||
@@ -585,18 +664,11 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
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++) {
|
||||
if (!programObject->IsValidUniformLocation(location + offset)) {
|
||||
RecordInvalidUniformLocationError(__func__, location + offset, "the current program object");
|
||||
return;
|
||||
}
|
||||
Uniform_State<ItemCount>(*programObject, location + offset, value + offset * ItemCount);
|
||||
}
|
||||
}
|
||||
@@ -616,17 +688,12 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
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++) {
|
||||
if (!programObject->IsValidUniformLocation(location + offset)) {
|
||||
RecordInvalidUniformLocationError(__func__, location + offset,
|
||||
"program " + std::to_string(program));
|
||||
return;
|
||||
}
|
||||
Uniform_State<ItemCount>(*programObject, location + offset, value + offset * ItemCount);
|
||||
}
|
||||
}
|
||||
@@ -744,19 +811,12 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
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 (GLint i = 0; i < count; i++) {
|
||||
if (!programObject->IsValidUniformLocation(location + i)) {
|
||||
RecordInvalidUniformLocationError(__func__, location + i, "the current program object");
|
||||
return;
|
||||
}
|
||||
if (transpose == GL_TRUE) {
|
||||
// Transpose the matrix before uploading
|
||||
GLfloat transposedMatrix[4];
|
||||
@@ -782,20 +842,13 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
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
|
||||
// Handle padding in mat3 correctly!!
|
||||
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) {
|
||||
// Transpose the matrix before uploading
|
||||
GLfloat transposedMatrix[9];
|
||||
@@ -825,19 +878,12 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
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 (GLint i = 0; i < count; i++) {
|
||||
if (!programObject->IsValidUniformLocation(location + i)) {
|
||||
RecordInvalidUniformLocationError(__func__, location + i, "the current program object");
|
||||
return;
|
||||
}
|
||||
if (transpose == GL_TRUE) {
|
||||
// Transpose the matrix before uploading
|
||||
GLfloat transposedMatrix[16];
|
||||
@@ -865,17 +911,11 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
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++) {
|
||||
if (!programObject->IsValidUniformLocation(location + i)) {
|
||||
RecordInvalidUniformLocationError(__func__, location + i, "program " + std::to_string(program));
|
||||
return;
|
||||
}
|
||||
if (transpose == GL_TRUE) {
|
||||
GLfloat transposedMatrix[4];
|
||||
TransposeMatrix2x2(value + i * 4, transposedMatrix);
|
||||
@@ -901,17 +941,11 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
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++) {
|
||||
if (!programObject->IsValidUniformLocation(location + i)) {
|
||||
RecordInvalidUniformLocationError(__func__, location + i, "program " + std::to_string(program));
|
||||
return;
|
||||
}
|
||||
if (transpose == GL_TRUE) {
|
||||
GLfloat transposedMatrix[9];
|
||||
TransposeMatrix3x3(value + i * 9, transposedMatrix);
|
||||
@@ -941,17 +975,11 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
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++) {
|
||||
if (!programObject->IsValidUniformLocation(location + i)) {
|
||||
RecordInvalidUniformLocationError(__func__, location + i, "program " + std::to_string(program));
|
||||
return;
|
||||
}
|
||||
if (transpose == GL_TRUE) {
|
||||
GLfloat transposedMatrix[16];
|
||||
TransposeMatrix4x4(value + i * 16, transposedMatrix);
|
||||
@@ -1033,22 +1061,52 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
break;
|
||||
}
|
||||
case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: {
|
||||
// TODO: deduct global ubo?
|
||||
*params = programObject->GetActiveUniformBlocksCount();
|
||||
*params = programObject->GetUniformBlockActiveUniformCount(uniformBlockIndex);
|
||||
MGLOG_D("%s: GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS = %d", __func__, *params);
|
||||
break;
|
||||
}
|
||||
case GL_UNIFORM_BLOCK_BINDING: {
|
||||
// TODO
|
||||
MGLOG_D("%s: GL_UNIFORM_BLOCK_BINDING = <TODO>", __func__, *params);
|
||||
*params = static_cast<GLint>(programObject->GetUniformBlockBinding(uniformBlockIndex));
|
||||
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:
|
||||
*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:
|
||||
*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:
|
||||
*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:
|
||||
*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:
|
||||
*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:
|
||||
*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:
|
||||
MGLOG_E("%s: unknown pname = %p %s", __func__, pname, MG_Util::ConvertGLEnumToString(pname).c_str());
|
||||
MG_State::pGLContext->RecordError(
|
||||
@@ -1084,7 +1142,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
const auto& name = programObject->GetUniformBlockName(uniformBlockIndex);
|
||||
CopyStr(bufSize, length, uniformBlockName, name.c_str(), (GLsizei)name.length());
|
||||
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) {
|
||||
@@ -1166,6 +1224,16 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
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) {
|
||||
GetAttachedShaders_State(program, maxCount, count, shaders);
|
||||
}
|
||||
@@ -1206,6 +1274,10 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
GetUniformiv_State(program, location, params);
|
||||
}
|
||||
|
||||
void GetUniformuiv(GLuint program, GLint location, GLuint* params) {
|
||||
GetUniformuiv_State(program, location, params);
|
||||
}
|
||||
|
||||
GLboolean IsProgram(GLuint program) {
|
||||
return IsProgram_State(program);
|
||||
}
|
||||
@@ -1263,6 +1335,25 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
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) {
|
||||
Uniform1fv_State(location, count, value);
|
||||
}
|
||||
@@ -1295,6 +1386,22 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
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) {
|
||||
UniformMatrix2fv_State(location, count, transpose, value);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,10 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
GLchar* name);
|
||||
void GetActiveUniform(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLint* size, GLenum* type,
|
||||
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);
|
||||
GLint GetAttribLocation(GLuint program, const GLchar* name);
|
||||
void GetProgramiv(GLuint program, GLenum pname, GLint* params);
|
||||
@@ -32,6 +36,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
GLint GetUniformLocation(GLuint program, const GLchar* name);
|
||||
void GetUniformfv(GLuint program, GLint location, GLfloat* params);
|
||||
void GetUniformiv(GLuint program, GLint location, GLint* params);
|
||||
void GetUniformuiv(GLuint program, GLint location, GLuint* params);
|
||||
GLboolean IsProgram(GLuint program);
|
||||
GLboolean IsShader(GLuint shader);
|
||||
void LinkProgram(GLuint program);
|
||||
@@ -45,6 +50,10 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
void Uniform2i(GLint location, GLint v0, GLint v1);
|
||||
void Uniform3i(GLint location, GLint v0, GLint v1, GLint v2);
|
||||
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 Uniform2fv(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 Uniform3iv(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 UniformMatrix3fv(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>
|
||||
|
||||
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,
|
||||
::MobileGL::BlendEquation& outEquation) {
|
||||
outEquation = MG_Util::ConvertGLEnumToBlendEquation(mode);
|
||||
@@ -27,6 +53,43 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
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) {
|
||||
if (width < 0 || height < 0) {
|
||||
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) {
|
||||
// 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) {
|
||||
// TODO: implement
|
||||
StencilOpSeparate_State(GL_FRONT_AND_BACK, fail, zfail, zpass);
|
||||
}
|
||||
|
||||
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) {
|
||||
// TODO: implement
|
||||
StencilMaskSeparate_State(GL_FRONT_AND_BACK, 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) {
|
||||
// TODO: implement
|
||||
StencilFuncSeparate_State(GL_FRONT_AND_BACK, func, ref, mask);
|
||||
}
|
||||
|
||||
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) {
|
||||
// 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) {
|
||||
// TODO: implement
|
||||
MG_State::pGLContext->SetPolygonOffset(static_cast<Float>(factor), static_cast<Float>(units));
|
||||
}
|
||||
|
||||
void PolygonMode_State(GLenum face, GLenum mode) {
|
||||
@@ -86,7 +196,15 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -114,14 +232,36 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
|
||||
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) {
|
||||
// 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) {
|
||||
if (!ValidateIndexedBlendCapability(target, index, "IsEnabledi_State")) {
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
CapabilityInput capInput = MG_Util::ConvertGLEnumToCapabilityInput(target);
|
||||
if (capInput == CapabilityInput::Unknown) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
@@ -135,6 +275,18 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
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) {
|
||||
CapabilityInput capInput = MG_Util::ConvertGLEnumToCapabilityInput(cap);
|
||||
if (capInput == CapabilityInput::Unknown) {
|
||||
@@ -197,7 +349,8 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -289,7 +442,8 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -359,6 +513,10 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
|
||||
void Disablei_State(GLenum target, GLuint index) {
|
||||
if (!ValidateIndexedBlendCapability(target, index, "Disablei_State")) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto capInput = MG_Util::ConvertGLEnumToCapabilityInput(target);
|
||||
if (capInput == CapabilityInput::Unknown) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
@@ -373,6 +531,10 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
|
||||
void Enablei_State(GLenum target, GLuint index) {
|
||||
if (!ValidateIndexedBlendCapability(target, index, "Enablei_State")) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto capInput = MG_Util::ConvertGLEnumToCapabilityInput(target);
|
||||
if (capInput == CapabilityInput::Unknown) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
@@ -403,6 +565,10 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
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) {
|
||||
Disablei_State(target, index);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
void BlendEquationSeparatei(GLuint buf, GLenum modeRGB, GLenum modeAlpha);
|
||||
void BlendFunci(GLuint buf, GLenum src, GLenum dst);
|
||||
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 Enablei(GLenum target, GLuint index);
|
||||
void BlendFunc(GLenum sfactor, GLenum dfactor);
|
||||
|
||||
@@ -13,7 +13,31 @@
|
||||
#include <MG_Util/Converters/MGToGL/TextureEnumConverter.h>
|
||||
|
||||
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) {
|
||||
if (param == nullptr) return;
|
||||
if (!SamplerImpl::ValidateSamplerName(sampler)) return;
|
||||
|
||||
Bool doesSamplerObjectCreated = MG_State::pGLContext->ValidateSamplerObject(sampler);
|
||||
@@ -23,6 +47,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
auto& samplerObj = MG_State::pGLContext->GetSamplerObject(sampler);
|
||||
if (!SamplerImpl::ValidateSamplerObject(sampler)) return;
|
||||
if (!ValidateSamplerParameterValue(pname, param, isFloat, isInteger)) return;
|
||||
|
||||
using namespace MG_Util;
|
||||
switch (pname) {
|
||||
@@ -65,6 +90,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
|
||||
void GetSamplerParam_State(GLuint sampler, GLenum pname, void* params, bool isFloat, bool isInteger) {
|
||||
if (params == nullptr) return;
|
||||
if (!SamplerImpl::ValidateSamplerName(sampler)) return;
|
||||
|
||||
Bool doesSamplerObjectCreated = MG_State::pGLContext->ValidateSamplerObject(sampler);
|
||||
|
||||
@@ -9,35 +9,239 @@
|
||||
#include "GL_Sync.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 {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
return 0;
|
||||
return FenceSync_State(condition, flags);
|
||||
}
|
||||
|
||||
GLboolean IsSync(GLsync sync) {
|
||||
return IsSync_State(sync);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
|
||||
namespace MobileGL::MG_Impl::GLImpl {
|
||||
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);
|
||||
void GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values);
|
||||
void DeleteSync(GLsync sync);
|
||||
} // namespace MobileGL::MG_Impl::GLImpl
|
||||
|
||||
@@ -31,6 +31,21 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
static SharedPtr<MG_State::GLState::ITextureObject> nullTextureObject;
|
||||
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(
|
||||
TextureUploadTarget textureUploadTarget, TextureTarget textureTarget) {
|
||||
if (TextureImpl::IsProxyTextureTarget(textureUploadTarget)) {
|
||||
@@ -360,7 +375,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
// ======================= Processing ================================
|
||||
auto& textureObject = GetTextureObjectByTarget(textureUploadTarget, textureTarget);
|
||||
if (!textureObject) return;
|
||||
THROW_UNIMPL_EXCEPTION;
|
||||
SetTextureBorderColorFromFloats(textureObject, params);
|
||||
break;
|
||||
}
|
||||
case GL_TEXTURE_SWIZZLE_RGBA: {
|
||||
@@ -401,8 +416,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
// ======================= Processing ================================
|
||||
auto& textureObject = GetTextureObjectByTarget(textureUploadTarget, textureTarget);
|
||||
if (!textureObject) return;
|
||||
|
||||
THROW_UNIMPL_EXCEPTION;
|
||||
SetTextureBorderColorFromInts(textureObject, params);
|
||||
break;
|
||||
}
|
||||
case GL_TEXTURE_SWIZZLE_RGBA: {
|
||||
@@ -436,7 +450,11 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
void TexParameterIiv_State(GLenum target, GLenum pname, const GLint* params) {
|
||||
switch (pname) {
|
||||
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;
|
||||
}
|
||||
case GL_TEXTURE_SWIZZLE_RGBA: {
|
||||
@@ -470,7 +488,12 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
void TexParameterIuiv_State(GLenum target, GLenum pname, const GLuint* params) {
|
||||
switch (pname) {
|
||||
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;
|
||||
}
|
||||
case GL_TEXTURE_SWIZZLE_RGBA: {
|
||||
@@ -806,13 +829,17 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
|
||||
void GetTexParameterIuiv_State(GLenum target, GLenum pname, GLuint* params) {
|
||||
// TODO: implement
|
||||
THROW_UNIMPL_EXCEPTION;
|
||||
if (params == nullptr) return;
|
||||
|
||||
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) {
|
||||
// TODO: implement
|
||||
THROW_UNIMPL_EXCEPTION;
|
||||
GetTexParameteriv_State(target, pname, params);
|
||||
}
|
||||
|
||||
void GetTexParameteriv_State(GLenum target, GLenum pname, GLint* params) {
|
||||
@@ -855,9 +882,48 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
break;
|
||||
case GL_TEXTURE_BASE_LEVEL:
|
||||
if (params) {
|
||||
*params = static_cast<GLint>(textureObject->GetLevelRange().x());
|
||||
}
|
||||
break;
|
||||
case GL_TEXTURE_MAX_LEVEL:
|
||||
if (params) {
|
||||
*params = static_cast<GLint>(textureObject->GetLevelRange().y());
|
||||
}
|
||||
break;
|
||||
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:
|
||||
if (params) {
|
||||
*params = (GLint)MG_Util::ConvertSamplerWrapModeToGLEnum(textureObject->GetSamplerObject()->GetWrapS());
|
||||
@@ -933,14 +999,50 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
break;
|
||||
case GL_TEXTURE_BASE_LEVEL:
|
||||
if (params) {
|
||||
*params = static_cast<GLfloat>(textureObject->GetLevelRange().x());
|
||||
}
|
||||
break;
|
||||
case GL_TEXTURE_MAX_LEVEL:
|
||||
if (params) {
|
||||
*params = static_cast<GLfloat>(textureObject->GetLevelRange().y());
|
||||
}
|
||||
break;
|
||||
case GL_TEXTURE_SWIZZLE_R:
|
||||
if (params) {
|
||||
*params = static_cast<GLfloat>(
|
||||
MG_Util::ConvertTextureSwizzleParamToGLEnum(textureObject->GetSwizzleParam(TextureSwizzleParam::Red)));
|
||||
}
|
||||
break;
|
||||
case GL_TEXTURE_SWIZZLE_G:
|
||||
if (params) {
|
||||
*params = static_cast<GLfloat>(MG_Util::ConvertTextureSwizzleParamToGLEnum(
|
||||
textureObject->GetSwizzleParam(TextureSwizzleParam::Green)));
|
||||
}
|
||||
break;
|
||||
case GL_TEXTURE_SWIZZLE_B:
|
||||
if (params) {
|
||||
*params = static_cast<GLfloat>(MG_Util::ConvertTextureSwizzleParamToGLEnum(
|
||||
textureObject->GetSwizzleParam(TextureSwizzleParam::Blue)));
|
||||
}
|
||||
break;
|
||||
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_BORDER_COLOR:
|
||||
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:
|
||||
if (params) {
|
||||
*params =
|
||||
@@ -1386,7 +1488,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
|
||||
// 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 ================================
|
||||
TextureUploadTarget textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
|
||||
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
|
||||
@@ -1399,7 +1501,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidEnum,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", "Invalid texture target"));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate level
|
||||
@@ -1407,7 +1509,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidValue,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", "Level must be non-negative"));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate format
|
||||
@@ -1415,7 +1517,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidEnum,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", "Invalid format"));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate type
|
||||
@@ -1423,7 +1525,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidEnum,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", "Invalid pixel data type"));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get texture object
|
||||
@@ -1438,7 +1540,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State",
|
||||
"No valid texture bound to target"));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check texture completeness
|
||||
@@ -1446,7 +1548,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidOperation,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", "Texture is incomplete"));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check PBO state
|
||||
@@ -1459,7 +1561,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidOperation, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State",
|
||||
"Pixel pack buffer is currently mapped"));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check alignment
|
||||
@@ -1469,7 +1571,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
ErrorCode::InvalidOperation,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State",
|
||||
"Pixel data not aligned for pixel pack buffer"));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1482,21 +1584,11 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
ErrorCode::InvalidOperation,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State",
|
||||
"No stencil buffer for stencil index format"));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for multisampling
|
||||
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;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */
|
||||
@@ -1538,9 +1630,6 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
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;
|
||||
if (!bindImageTexture) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
@@ -1549,6 +1638,9 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
"Backend does not support image texture binding."));
|
||||
return;
|
||||
}
|
||||
|
||||
MG_State::pGLContext->GetImageTextureBinding(static_cast<Int>(unit))
|
||||
.Bind(textureObject, 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) {
|
||||
GetTexImage_State(target, level, format, type, pixels);
|
||||
if (!GetTexImage_State(target, level, format, type, pixels)) return;
|
||||
GetTexImage_Backend(target, level, format, type, pixels);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,11 @@
|
||||
// End of Source File Header
|
||||
|
||||
#include "ProxyTexture.h"
|
||||
#include <MG_State/GLState/TextureState/TextureObject1D.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 {
|
||||
UniquePtr<ProxyTextureManager> pProxyTextureManager;
|
||||
@@ -37,7 +41,39 @@ namespace MobileGL::MG_Impl::GLImpl::TextureImpl {
|
||||
m_proxyTexturesMap.erase(it);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,8 +11,64 @@
|
||||
#include <MG_State/GLState/Core.h>
|
||||
#include <MG_State/GLState/ErrorState/Error.h>
|
||||
#include <MG_Util/Converters/GLToMG/DataTypeConverter.h>
|
||||
#include <MG_Util/Converters/MGToGL/DataTypeConverter.h>
|
||||
|
||||
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) {
|
||||
if (!VertexArrayImpl::ValidateVertexAttributeIndex(index)) return;
|
||||
|
||||
@@ -163,6 +219,287 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
|
||||
/* @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) {
|
||||
VertexAttribDivisor_State(index, divisor);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,26 @@
|
||||
|
||||
namespace MobileGL::MG_Impl::GLImpl {
|
||||
/* @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);
|
||||
GLboolean IsVertexArray(GLuint array);
|
||||
void DisableVertexAttribArray(GLuint index);
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace MobileGL::MG_Impl {
|
||||
stencilTex->AllocateStorage(TextureUploadTarget::Texture2D, 0, {{512, 512, 1}, 0});
|
||||
// stencilTex->SetMipmapLevel({{512, 512, 1}, 0, false, 0, {nullptr, 0}});
|
||||
fbo0->AttachTexture(FramebufferAttachmentType::Color0, colorTex);
|
||||
fbo0->AttachTexture(FramebufferAttachmentType::BackLeft, colorTex);
|
||||
fbo0->AttachTexture(FramebufferAttachmentType::Depth, depthTex);
|
||||
fbo0->AttachTexture(FramebufferAttachmentType::Stencil, stencilTex);
|
||||
GLImpl::FramebufferImpl::pDefaultFramebufferInfo =
|
||||
|
||||
@@ -1139,6 +1139,21 @@ namespace MobileGL {
|
||||
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,
|
||||
const EGLAttrib* attribList) {
|
||||
const std::lock_guard<std::recursive_mutex> lock(m_mutex);
|
||||
|
||||
@@ -87,6 +87,7 @@ namespace MobileGL {
|
||||
EGLContextHandle GetCurrentContext() const;
|
||||
EGLDisplayHandle GetCurrentDisplay() const;
|
||||
EGLSurfaceHandle GetCurrentSurface(EGLint readdraw) const;
|
||||
Bool IsDoubleBufferedSurface(EGLSurfaceHandle surface) const;
|
||||
|
||||
// Sync
|
||||
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) {
|
||||
if (markMapped) {
|
||||
m_isMapped = true;
|
||||
auto a = BufferMappingAccessBit::Coherent | BufferMappingAccessBit::Read;
|
||||
m_mappingAccess = (read ? BufferMappingAccessBit::Read : BufferMappingAccessBit::Null) |
|
||||
(write ? BufferMappingAccessBit::Write : BufferMappingAccessBit::Null);
|
||||
m_mappedRange = {0, m_size};
|
||||
if (write) {
|
||||
m_change.Bits |= BufferChangeBits::ForbidInvalidationBit;
|
||||
m_change.Bits |= BufferChangeBits::ForbidUnsynchronizationBit;
|
||||
}
|
||||
|
||||
if (m_mappingAccess & BufferMappingAccessBit::Write) {
|
||||
m_stagingData.resize(m_size);
|
||||
@@ -148,6 +151,13 @@ namespace MobileGL::MG_State::GLState {
|
||||
m_isMapped = true;
|
||||
m_mappingAccess = access;
|
||||
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) {
|
||||
m_stagingData.resize(range.end - range.start);
|
||||
@@ -162,14 +172,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
m_ownsStagingData = false;
|
||||
return m_dataPtr->data() + range.start;
|
||||
}
|
||||
|
||||
m_change.Bits |=
|
||||
!(access & BufferMappingAccessBit::InvalidateBuffer || access & BufferMappingAccessBit::InvalidateRange)
|
||||
? BufferChangeBits::ForbidInvalidationBit
|
||||
: BufferChangeBits::None;
|
||||
m_change.Bits |= !(access & BufferMappingAccessBit::Unsynchronized)
|
||||
? BufferChangeBits::ForbidUnsynchronizationBit
|
||||
: BufferChangeBits::None;
|
||||
}
|
||||
|
||||
const SharedPtr<Data>& BufferObject::GetDataReadOnly() const {
|
||||
@@ -209,6 +211,18 @@ namespace MobileGL::MG_State::GLState {
|
||||
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 {
|
||||
return m_isMapped ? m_mappingAccess : BufferMappingAccessBit::Null;
|
||||
}
|
||||
|
||||
@@ -94,6 +94,7 @@ namespace MobileGL {
|
||||
SizeT GetSize() const;
|
||||
BufferUsage GetUsage() const;
|
||||
Range1D GetMappedRange() const;
|
||||
void* GetMappedPointer();
|
||||
const SharedPtr<Data>& GetDataReadOnly() const;
|
||||
Flags<BufferMappingAccessBit> GetMappingAccess() const;
|
||||
Uint GetExternalIndex() const;
|
||||
|
||||
@@ -56,6 +56,14 @@ namespace MobileGL::MG_State::GLState {
|
||||
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_indexGenerator.Delete(index);
|
||||
|
||||
@@ -285,6 +285,34 @@ namespace MobileGL::MG_State {
|
||||
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) {
|
||||
m_renderState.SetCapability(cap, enabled);
|
||||
}
|
||||
@@ -337,6 +365,14 @@ namespace MobileGL::MG_State {
|
||||
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) {
|
||||
m_renderState.SetDepthFunc(func);
|
||||
}
|
||||
@@ -353,6 +389,23 @@ namespace MobileGL::MG_State {
|
||||
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) {
|
||||
m_renderState.SetColorMask(mask);
|
||||
}
|
||||
@@ -381,9 +434,45 @@ namespace MobileGL::MG_State {
|
||||
m_renderState.SetClearStencil(stencil);
|
||||
}
|
||||
|
||||
Uint32 GLContext::GetClearStencil() const {
|
||||
return m_renderState.GetClearStencil();
|
||||
}
|
||||
Uint32 GLContext::GetClearStencil() const {
|
||||
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) {
|
||||
m_renderState.SetPixelStoreParam(param, value);
|
||||
|
||||
@@ -102,6 +102,13 @@ namespace MobileGL {
|
||||
const RenderStateParameters& GetRenderStateParameters() const;
|
||||
void SetViewport(IntVec4 viewport); // 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);
|
||||
Bool IsCapabilityEnabled(CapabilityInput cap) const;
|
||||
void SetCapabilityIndexed(CapabilityInput cap, Uint index, Bool enabled);
|
||||
@@ -117,10 +124,17 @@ namespace MobileGL {
|
||||
void GetBlendEquation(BlendEquation& color, BlendEquation& alpha) const;
|
||||
void SetBlendEquationIndexed(Uint index, BlendEquation color, BlendEquation alpha);
|
||||
void GetBlendEquationIndexed(Uint index, BlendEquation& color, BlendEquation& alpha) const;
|
||||
void SetLogicOp(LogicOperation logicOp);
|
||||
LogicOperation GetLogicOp() const;
|
||||
void SetDepthFunc(DepthTestFunc func);
|
||||
DepthTestFunc GetDepthFunc() const;
|
||||
void SetDepthMask(Bool flag);
|
||||
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);
|
||||
BoolVec4 GetColorMask() const;
|
||||
void SetClearColor(FloatVec4 color);
|
||||
@@ -129,6 +143,15 @@ namespace MobileGL {
|
||||
Float GetClearDepth() const;
|
||||
void SetClearStencil(Int stencil);
|
||||
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);
|
||||
Int GetPixelStoreParam(PixelStoreParam param) const;
|
||||
PixelStoreParameters GetPixelStoreParameters(Bool isUnpack) const;
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
namespace MobileGL::MG_State::GLState {
|
||||
// FramebufferAttachmentObject
|
||||
FramebufferAttachmentObject::FramebufferAttachmentObject(
|
||||
const SharedPtr<MG_State::GLState::ITextureObject>& texture, Int level)
|
||||
: m_texture(texture), m_textureLevel(level) {}
|
||||
const SharedPtr<MG_State::GLState::ITextureObject>& texture, TextureUploadTarget textureUploadTarget, Int level)
|
||||
: m_texture(texture), m_textureUploadTarget(textureUploadTarget), m_textureLevel(level) {}
|
||||
FramebufferAttachmentObject::FramebufferAttachmentObject(const SharedPtr<RenderbufferObject>& renderbuffer)
|
||||
: m_renderbuffer(renderbuffer) {}
|
||||
FramebufferAttachmentObject::FramebufferAttachmentObject(Bool IsValid)
|
||||
@@ -45,6 +45,10 @@ namespace MobileGL::MG_State::GLState {
|
||||
return m_textureLevel;
|
||||
}
|
||||
|
||||
TextureUploadTarget FramebufferAttachmentObject::GetTextureUploadTarget() const {
|
||||
return m_textureUploadTarget;
|
||||
}
|
||||
|
||||
Bool FramebufferAttachmentObject::IsComplete() const {
|
||||
if (IsTexture()) {
|
||||
Bool complete = m_texture->IsComplete();
|
||||
@@ -59,11 +63,18 @@ namespace MobileGL::MG_State::GLState {
|
||||
|
||||
IntVec3 FramebufferAttachmentObject::GetSize() const {
|
||||
if (IsTexture()) {
|
||||
// TODO: get correct upload target
|
||||
MOBILEGL_ASSERT(nullptr != static_cast<MG_State::GLState::TextureObjectMipmap*>(m_texture.get()),
|
||||
"Texture object here should always be an object with mipmap");
|
||||
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()) {
|
||||
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_attachmentObjects.fill(FramebufferAttachmentObject(false));
|
||||
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);
|
||||
}
|
||||
|
||||
void FramebufferObject::AttachTexture(FramebufferAttachmentType type, const SharedPtr<ITextureObject>& texture,
|
||||
int level) {
|
||||
m_attachmentObjects[static_cast<SizeT>(type)] = FramebufferAttachmentObject(texture, level);
|
||||
TextureUploadTarget textureUploadTarget, int level) {
|
||||
m_attachmentObjects[static_cast<SizeT>(type)] = FramebufferAttachmentObject(texture, textureUploadTarget, level);
|
||||
BumpAttachmentVersion(type);
|
||||
}
|
||||
|
||||
@@ -150,6 +164,12 @@ namespace MobileGL::MG_State::GLState {
|
||||
return m_drawBuffers;
|
||||
}
|
||||
|
||||
void FramebufferObject::SetReadBuffer(FramebufferAttachmentType buf) {
|
||||
if (m_readBuffer == buf) return;
|
||||
m_readBuffer = buf;
|
||||
++m_objectVersion;
|
||||
}
|
||||
|
||||
Uint FramebufferObject::GetExternalIndex() const {
|
||||
return m_externalIndex;
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@ namespace MobileGL {
|
||||
class FramebufferAttachmentObject {
|
||||
public:
|
||||
explicit FramebufferAttachmentObject(const SharedPtr<MG_State::GLState::ITextureObject>& texture,
|
||||
TextureUploadTarget textureUploadTarget,
|
||||
Int level = 0);
|
||||
explicit FramebufferAttachmentObject(const SharedPtr<RenderbufferObject>& renderbuffer);
|
||||
explicit FramebufferAttachmentObject(Bool IsValid = true);
|
||||
@@ -83,6 +84,7 @@ namespace MobileGL {
|
||||
const SharedPtr<MG_State::GLState::ITextureObject>& GetTexture() const;
|
||||
const SharedPtr<RenderbufferObject>& GetRenderbuffer() const;
|
||||
Int GetTextureLevel() const;
|
||||
TextureUploadTarget GetTextureUploadTarget() const;
|
||||
Bool IsComplete() const;
|
||||
IntVec3 GetSize() const;
|
||||
Bool IsValid() const;
|
||||
@@ -90,6 +92,7 @@ namespace MobileGL {
|
||||
private:
|
||||
SharedPtr<MG_State::GLState::ITextureObject> m_texture = nullptr;
|
||||
SharedPtr<RenderbufferObject> m_renderbuffer = nullptr;
|
||||
TextureUploadTarget m_textureUploadTarget = TextureUploadTarget::Unknown;
|
||||
Int m_textureLevel = 0;
|
||||
Bool m_isValid = true;
|
||||
};
|
||||
@@ -108,7 +111,8 @@ namespace MobileGL {
|
||||
|
||||
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 Detach(FramebufferAttachmentType type);
|
||||
const FramebufferAttachmentObject& GetAttachment(FramebufferAttachmentType type) const;
|
||||
@@ -117,7 +121,7 @@ namespace MobileGL {
|
||||
// aka. `buffer` as in glDrawBuffers/glReadBuffers
|
||||
void SetDrawBuffer(Uint index, FramebufferAttachmentType buffer);
|
||||
const FramebufferAttachmentArray& GetDrawBuffers() const;
|
||||
void SetReadBuffer(FramebufferAttachmentType buf) { m_readBuffer = buf; }
|
||||
void SetReadBuffer(FramebufferAttachmentType buf);
|
||||
FramebufferAttachmentType GetReadBuffer() const { return m_readBuffer; }
|
||||
|
||||
FramebufferAttachmentVersionArray GetAllFramebufferAttachmentVersions() const {
|
||||
@@ -136,7 +140,7 @@ namespace MobileGL {
|
||||
FramebufferAttachmentVersionArray m_attachmentVersions;
|
||||
|
||||
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`)
|
||||
Uint16 m_objectVersion = 0;
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace MobileGL::MG_State::GLState {
|
||||
if (it != m_framebufferObjects.end()) {
|
||||
for (auto& bindingSlot : m_bindingSlots) {
|
||||
if (bindingSlot.GetBoundObject() == it->second) {
|
||||
bindingSlot.Bind(nullptr);
|
||||
bindingSlot.Bind(GetFramebufferObject(0));
|
||||
}
|
||||
}
|
||||
m_framebufferObjects.erase(it);
|
||||
|
||||
@@ -60,6 +60,27 @@ namespace {
|
||||
}
|
||||
|
||||
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) {
|
||||
MGLOG_D("ProgramObject %u: ShaderIsAttached check for shader %p", m_externalIndex, shader.get());
|
||||
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) {
|
||||
MGLOG_D("ProgramObject %u: Link start, shaders to link: %zu", m_externalIndex, m_shaders.size());
|
||||
++m_backendStateVersion;
|
||||
ResetLinkArtifacts();
|
||||
m_infoLog.clear();
|
||||
// Remove detached shaders first
|
||||
for (const auto& detachedShader : m_detachedShaders) {
|
||||
RemoveShader(detachedShader);
|
||||
@@ -163,7 +186,6 @@ namespace MobileGL::MG_State::GLState {
|
||||
"log:\n{}\nShader src:\n{}",
|
||||
MG_Util::ConvertGLEnumToString(shaderTypes[i]), m_shaders[i]->GetInfoLog(),
|
||||
m_shaders[i]->GetShaderSource());
|
||||
m_linkStatus = false;
|
||||
MGLOG_E("ProgramObject %u: Link failed - shader[%zu] compile status false. InfoLog:\n%s",
|
||||
m_externalIndex, i, m_infoLog.c_str());
|
||||
return;
|
||||
@@ -186,9 +208,9 @@ namespace MobileGL::MG_State::GLState {
|
||||
m_program = result.value();
|
||||
MGLOG_D("ProgramObject %u: LinkProgram succeeded, TProgram ptr %p", m_externalIndex, m_program.get());
|
||||
} else {
|
||||
m_linkStatus = false;
|
||||
m_infoLog = result.error().log;
|
||||
MGLOG_E("ProgramObject %u: LinkProgram failed. InfoLog:\n%s", m_externalIndex, m_infoLog.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
MGLOG_D("ProgramObject %u: Starting reflection", m_externalIndex);
|
||||
|
||||
@@ -40,11 +40,40 @@ namespace MobileGL::MG_State::GLState {
|
||||
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 {
|
||||
auto& uniform = m_program->getUniform(m_uniformIndexInTProgram[location]);
|
||||
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 {
|
||||
auto& uniform = m_program->getUniform(m_uniformIndexInTProgram[location]);
|
||||
return uniform.getType();
|
||||
@@ -56,6 +85,11 @@ namespace MobileGL::MG_State::GLState {
|
||||
auto& uniform = m_program->getUniform(m_uniformIndexInTProgram[location]);
|
||||
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 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]; }
|
||||
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(); }
|
||||
const void* GetUBOData() const { return m_globalUboScratch.data(); }
|
||||
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 GetActiveAttributesCount() const { return m_program->getNumPipeInputs(); }
|
||||
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 GetActiveUniformBlocksMaxNameLength() const { return m_uniformBlockNameMaxLength; }
|
||||
Uint GetUniformBlockIndex(const char* name) const {
|
||||
@@ -147,6 +185,16 @@ namespace MobileGL::MG_State::GLState {
|
||||
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
|
||||
void SetUniformBlockBinding(Uint index, Uint 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; }
|
||||
|
||||
private:
|
||||
void ResetLinkArtifacts();
|
||||
void DoReflection();
|
||||
void GenerateBinary();
|
||||
void WaitUntilGenerationCompleted() const;
|
||||
|
||||
@@ -16,10 +16,16 @@
|
||||
namespace MobileGL::MG_State::GLState {
|
||||
void ShaderObject::SetShaderSource(const String& source) {
|
||||
m_source = source;
|
||||
m_shader.reset();
|
||||
m_compileStatus = false;
|
||||
m_infoLog.clear();
|
||||
}
|
||||
|
||||
void ShaderObject::SetShaderSource(String&& source) {
|
||||
m_source = Move(source);
|
||||
m_shader.reset();
|
||||
m_compileStatus = false;
|
||||
m_infoLog.clear();
|
||||
}
|
||||
|
||||
void ShaderObject::Compile() {
|
||||
@@ -38,8 +44,10 @@ namespace MobileGL::MG_State::GLState {
|
||||
if (result) {
|
||||
m_compileStatus = true;
|
||||
m_shader = result.value();
|
||||
m_infoLog.clear();
|
||||
} else {
|
||||
m_compileStatus = false;
|
||||
m_shader.reset();
|
||||
m_infoLog = result.error().log;
|
||||
MGLOG_D("ShaderObject::Compile: Shader %d compilation failed.\nSource:\n%s\nInfoLog:\n%s\nSetting "
|
||||
"m_compileStatus = false as a result.",
|
||||
|
||||
@@ -12,6 +12,20 @@
|
||||
namespace MobileGL {
|
||||
namespace MG_State {
|
||||
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() {}
|
||||
|
||||
Uint RenderState::GetVersion() const {
|
||||
@@ -34,6 +48,44 @@ namespace MobileGL {
|
||||
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 --------------------
|
||||
void RenderState::SetCapability(CapabilityInput cap, Bool enabled) {
|
||||
#define SET_CAPABILITY(capability, flag) \
|
||||
@@ -44,9 +96,28 @@ namespace MobileGL {
|
||||
break;
|
||||
|
||||
switch (cap) {
|
||||
SET_CAPABILITY(ColorLogicOp, enabled);
|
||||
SET_CAPABILITY(DebugOutput, enabled);
|
||||
SET_CAPABILITY(DebugOutputSynchronous, enabled);
|
||||
SET_CAPABILITY(DepthTest, 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(StencilTest, enabled);
|
||||
SET_CAPABILITY(ProgramPointSize, enabled);
|
||||
case CapabilityInput::Blend: {
|
||||
Bool stateChanged = false;
|
||||
for (auto& blendState : m_parameters.BlendStates) {
|
||||
@@ -68,9 +139,28 @@ namespace MobileGL {
|
||||
case CapabilityInput::capability: \
|
||||
return m_parameters.capability##Enabled;
|
||||
switch (cap) {
|
||||
RETURN_CAPABILITY(ColorLogicOp);
|
||||
RETURN_CAPABILITY(DebugOutput);
|
||||
RETURN_CAPABILITY(DebugOutputSynchronous);
|
||||
RETURN_CAPABILITY(DepthTest);
|
||||
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(StencilTest);
|
||||
RETURN_CAPABILITY(ProgramPointSize);
|
||||
case CapabilityInput::Blend:
|
||||
return m_parameters.BlendStates[0].Enabled;
|
||||
default:
|
||||
@@ -206,6 +296,17 @@ namespace MobileGL {
|
||||
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 --------------------
|
||||
void RenderState::SetDepthFunc(DepthTestFunc func) {
|
||||
if (m_parameters.DepthFunc == func) return;
|
||||
@@ -229,6 +330,42 @@ namespace MobileGL {
|
||||
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 --------------------
|
||||
void RenderState::SetColorMask(BoolVec4 mask) {
|
||||
if (m_parameters.ColorMask == mask) return;
|
||||
@@ -275,6 +412,55 @@ namespace MobileGL {
|
||||
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 --------------------
|
||||
void RenderState::SetPixelStoreParam(PixelStoreParam param, Int value) {
|
||||
#define SET_PIXEL_STORE_PARAM(paramNameHead, paramNameTail, val) \
|
||||
|
||||
@@ -41,6 +41,27 @@ namespace MobileGL {
|
||||
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 {
|
||||
Never,
|
||||
Less,
|
||||
@@ -54,6 +75,26 @@ namespace MobileGL {
|
||||
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 {
|
||||
// Pack Parameters
|
||||
PackAlignment,
|
||||
@@ -155,12 +196,27 @@ namespace MobileGL {
|
||||
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 {
|
||||
// Rasterization
|
||||
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
|
||||
Array<PerBufferBlendState, MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS> BlendStates;
|
||||
LogicOperation LogicOp = LogicOperation::Copy;
|
||||
|
||||
// Depth
|
||||
Bool DepthTestEnabled = false;
|
||||
@@ -174,6 +230,12 @@ namespace MobileGL {
|
||||
FloatVec4 ClearColor = FloatVec4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
Float ClearDepth = 1.0f;
|
||||
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
|
||||
Bool CullFaceEnabled = false;
|
||||
@@ -181,7 +243,26 @@ namespace MobileGL {
|
||||
FrontFaceMode FrontFaceModeSetting = FrontFaceMode::CounterClockwise;
|
||||
|
||||
// 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 StencilTestEnabled = false;
|
||||
Bool ProgramPointSizeEnabled = false;
|
||||
IntVec4 ScissorBox = IntVec4(0, 0, 0, 0); // x, y, width, height
|
||||
};
|
||||
|
||||
@@ -197,6 +278,13 @@ namespace MobileGL {
|
||||
// Rasterization
|
||||
void SetViewport(IntVec4 viewport); // 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
|
||||
void SetCapability(CapabilityInput cap, Bool enabled);
|
||||
@@ -216,12 +304,19 @@ namespace MobileGL {
|
||||
void GetBlendEquation(BlendEquation& color, BlendEquation& alpha) const;
|
||||
void SetBlendEquationIndexed(Uint index, BlendEquation color, BlendEquation alpha);
|
||||
void GetBlendEquationIndexed(Uint index, BlendEquation& color, BlendEquation& alpha) const;
|
||||
void SetLogicOp(LogicOperation logicOp);
|
||||
LogicOperation GetLogicOp() const;
|
||||
|
||||
// Depth
|
||||
void SetDepthFunc(DepthTestFunc func);
|
||||
DepthTestFunc GetDepthFunc() const;
|
||||
void SetDepthMask(Bool flag);
|
||||
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
|
||||
void SetColorMask(BoolVec4 mask);
|
||||
@@ -234,6 +329,15 @@ namespace MobileGL {
|
||||
Float GetClearDepth() const;
|
||||
void SetClearStencil(Int stencil);
|
||||
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
|
||||
void SetPixelStoreParam(PixelStoreParam param, Int value);
|
||||
|
||||
@@ -76,6 +76,10 @@ namespace MobileGL {
|
||||
m_height = size.y();
|
||||
m_allocated = true;
|
||||
}
|
||||
|
||||
void RenderbufferObject::SetSamples(Int samples) {
|
||||
m_samples = samples;
|
||||
}
|
||||
} // namespace GLState
|
||||
} // namespace MG_State
|
||||
} // namespace MobileGL
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace MobileGL {
|
||||
Uint GetExternalIndex() const;
|
||||
void SetInternalFormat(TextureInternalFormat format);
|
||||
void AllocateStorage(IntVec2 size);
|
||||
void SetSamples(Int samples);
|
||||
Int GetWidth() const;
|
||||
Int GetHeight() const;
|
||||
TextureInternalFormat GetInternalFormat() const;
|
||||
@@ -47,7 +48,7 @@ namespace MobileGL {
|
||||
TextureInternalFormat m_internalFormat;
|
||||
Int m_width = 0;
|
||||
Int m_height = 0;
|
||||
Int m_samples = 0; // TODO: multisampling support
|
||||
Int m_samples = 0;
|
||||
Bool m_allocated = false;
|
||||
ComponentSizes m_componentSizes;
|
||||
};
|
||||
|
||||
@@ -57,10 +57,6 @@ namespace MobileGL {
|
||||
|
||||
void SamplerObject::SetLodRange(Float minLod, Float maxLod) {
|
||||
if (minLod == m_samplerParameters.minLod && maxLod == m_samplerParameters.maxLod) return;
|
||||
|
||||
if (minLod > maxLod) {
|
||||
THROW_EXCEPTION("minLod cannot be greater than maxLod");
|
||||
}
|
||||
m_samplerParameters.minLod = minLod;
|
||||
m_samplerParameters.maxLod = maxLod;
|
||||
++m_version;
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace MobileGL {
|
||||
|
||||
Uint TextureObject2DCube::GetIndexOfTextureUploadTarget(TextureUploadTarget target) const {
|
||||
MOBILEGL_ASSERT(TextureUploadTarget::CubeMapPositiveX <= target &&
|
||||
target <= TextureUploadTarget::ProxyCubeMap,
|
||||
target <= TextureUploadTarget::CubeMapNegativeZ,
|
||||
"Invalid TextureUploadTarget!");
|
||||
return (Uint)target - (Uint)TextureUploadTarget::CubeMapPositiveX;
|
||||
}
|
||||
|
||||
@@ -50,8 +50,8 @@ namespace MobileGL::MG_State::GLState {
|
||||
|
||||
void VertexArrayState::MarkVertexArrayForDeletion(Uint index) {
|
||||
if (m_indexGenerator.IsValid(index)) {
|
||||
if (m_boundVertexArray) {
|
||||
m_boundVertexArray = nullptr;
|
||||
if (m_boundVertexArray && m_boundVertexArray->GetExternalIndex() == index) {
|
||||
m_boundVertexArray = GetVertexArrayObject(0);
|
||||
}
|
||||
|
||||
if (ValidateVertexArrayObject(index)) {
|
||||
|
||||
@@ -46,6 +46,8 @@ TEST(DirectVulkanSanity, WindowCreation) {
|
||||
#include <EGL/egl.h>
|
||||
#ifdef _WIN32
|
||||
#define GLFW_EXPOSE_NATIVE_WIN32
|
||||
#elif defined(__linux__)
|
||||
#define GLFW_EXPOSE_NATIVE_X11
|
||||
#elif defined(__APPLE__)
|
||||
#define GLFW_EXPOSE_NATIVE_COCOA
|
||||
#endif
|
||||
@@ -74,9 +76,11 @@ TEST(DirectVulkanSanity, ContextCreation) {
|
||||
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
GLFWwindow* window = glfwCreateWindow(800, 600, "MobileGL ContextCreation", nullptr, nullptr);
|
||||
EGLNativeWindowType nativewindow = nullptr;
|
||||
EGLNativeWindowType nativewindow = 0;
|
||||
#ifdef _WIN32
|
||||
nativewindow = glfwGetWin32Window(window);
|
||||
#elif defined(__linux__)
|
||||
nativewindow = static_cast<EGLNativeWindowType>(glfwGetX11Window(window));
|
||||
#elif defined(__APPLE__)
|
||||
void* cocoaWindow = glfwGetCocoaWindow(window);
|
||||
ASSERT_NE(cocoaWindow, nullptr);
|
||||
@@ -95,6 +99,7 @@ TEST(DirectVulkanSanity, ContextCreation) {
|
||||
msgSendVoidObj(contentView, sel_registerName("setLayer:"), metalLayer);
|
||||
nativewindow = reinterpret_cast<EGLNativeWindowType>(metalLayer);
|
||||
#endif
|
||||
ASSERT_NE(nativewindow, static_cast<EGLNativeWindowType>(0));
|
||||
EGLSurface surface = eglCreateWindowSurface(display, config, nativewindow, nullptr);
|
||||
eglMakeCurrent(display, surface, surface, context);
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
#include <EGL/egl.h>
|
||||
#ifdef _WIN32
|
||||
#define GLFW_EXPOSE_NATIVE_WIN32
|
||||
#elif defined(__linux__)
|
||||
#define GLFW_EXPOSE_NATIVE_X11
|
||||
#elif defined(__APPLE__)
|
||||
#define GLFW_EXPOSE_NATIVE_COCOA
|
||||
#endif
|
||||
@@ -107,9 +109,11 @@ int main() {
|
||||
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
GLFWwindow* window = glfwCreateWindow(800, 600, "MobileGL ContextCreation", nullptr, nullptr);
|
||||
EGLNativeWindowType nativewindow = nullptr;
|
||||
EGLNativeWindowType nativewindow = 0;
|
||||
#ifdef _WIN32
|
||||
nativewindow = glfwGetWin32Window(window);
|
||||
#elif defined(__linux__)
|
||||
nativewindow = static_cast<EGLNativeWindowType>(glfwGetX11Window(window));
|
||||
#elif defined(__APPLE__)
|
||||
void* cocoaWindow = glfwGetCocoaWindow(window);
|
||||
MOBILEGL_ASSERT(cocoaWindow, "glfwGetCocoaWindow returned null");
|
||||
@@ -128,6 +132,7 @@ int main() {
|
||||
msgSendVoidObj(contentView, sel_registerName("setLayer:"), metalLayer);
|
||||
nativewindow = reinterpret_cast<EGLNativeWindowType>(metalLayer);
|
||||
#endif
|
||||
MOBILEGL_ASSERT(nativewindow, "Failed to acquire native window handle for EGL window surface creation");
|
||||
EGLSurface surface = eglCreateWindowSurface(display, config, nativewindow, nullptr);
|
||||
eglMakeCurrent(display, surface, surface, context);
|
||||
|
||||
|
||||
@@ -48,11 +48,14 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
return false;
|
||||
}
|
||||
|
||||
Bool allRequiredLoaded = true;
|
||||
|
||||
#define INIT_GLES_FUNC(name) \
|
||||
do { \
|
||||
funcs.name = (MG_External::GLES::name##_PTR)procAddress(#name); \
|
||||
if (!funcs.name) { \
|
||||
MGLOG_E("Failed to load GLES function: %s", #name); \
|
||||
allRequiredLoaded = false; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
@@ -149,6 +152,8 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
INIT_GLES_FUNC(glIsTexture)
|
||||
INIT_GLES_FUNC(glLineWidth)
|
||||
INIT_GLES_FUNC(glLinkProgram)
|
||||
INIT_GLES_FUNC(glLogicOp)
|
||||
INIT_GLES_FUNC(glPointSize)
|
||||
INIT_GLES_FUNC(glPixelStorei)
|
||||
INIT_GLES_FUNC(glPolygonOffset)
|
||||
INIT_GLES_FUNC(glReadPixels)
|
||||
@@ -428,7 +433,7 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
INIT_GLES_FUNC(glMultiDrawElementsIndirectEXT)
|
||||
INIT_GLES_FUNC(glMultiDrawElementsBaseVertexEXT)
|
||||
}
|
||||
return true;
|
||||
return allRequiredLoaded;
|
||||
}
|
||||
|
||||
Bool AcquireEGLFunctions(MG_External::EGLFunctionsTable& funcs) {
|
||||
@@ -438,11 +443,15 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
MGLOG_E("Failed to open libEGL.so");
|
||||
return false;
|
||||
}
|
||||
|
||||
Bool allRequiredLoaded = true;
|
||||
|
||||
#define INIT_EGL_FUNC(name) \
|
||||
do { \
|
||||
funcs.name = (MG_External::EGL::name##_PTR)ProcAddress(eglLib, #name); \
|
||||
if (!funcs.name) { \
|
||||
MGLOG_E("Failed to load EGL function: %s", #name); \
|
||||
allRequiredLoaded = false; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
@@ -495,7 +504,7 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
INIT_EGL_FUNC(eglGetPlatformDisplay)
|
||||
INIT_EGL_FUNC(eglWaitSync)
|
||||
}
|
||||
return true;
|
||||
return allRequiredLoaded;
|
||||
}
|
||||
|
||||
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:");
|
||||
glesFuncs.glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &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;
|
||||
}
|
||||
|
||||
@@ -238,6 +238,8 @@ namespace MobileGL {
|
||||
GL_FUNC_TYPEDEF(GLboolean, glIsTexture, GLuint texture)
|
||||
GL_FUNC_TYPEDEF(void, glLineWidth, GLfloat width)
|
||||
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, glPolygonOffset, GLfloat factor, GLfloat units)
|
||||
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(glLineWidth)
|
||||
GL_FUNC_DECL(glLinkProgram)
|
||||
GL_FUNC_DECL(glLogicOp)
|
||||
GL_FUNC_DECL(glPointSize)
|
||||
GL_FUNC_DECL(glPixelStorei)
|
||||
GL_FUNC_DECL(glPolygonOffset)
|
||||
GL_FUNC_DECL(glReadPixels)
|
||||
@@ -1015,6 +1019,53 @@ namespace MobileGL {
|
||||
Bool SupportsPersistentMapping = false;
|
||||
Bool SupportsNorm16Texture = false;
|
||||
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
|
||||
|
||||
|
||||
@@ -15,6 +15,29 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
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 loaded{};
|
||||
if (instance == VK_NULL_HANDLE) {
|
||||
@@ -83,6 +106,57 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
caps.DeviceName = p.deviceName;
|
||||
caps.DriverVersionString = DecodeDriverVersion(p.driverVersion);
|
||||
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;
|
||||
}
|
||||
@@ -93,5 +167,53 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
caps.DeviceName = properties.deviceName;
|
||||
caps.DriverVersionString = DecodeDriverVersion(properties.driverVersion);
|
||||
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
|
||||
|
||||
@@ -16,6 +16,54 @@ namespace MobileGL {
|
||||
String DeviceName;
|
||||
String DriverVersionString;
|
||||
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_Util::BackendLoader {
|
||||
|
||||
@@ -24,6 +24,8 @@ namespace MobileGL {
|
||||
return DataType::Int32;
|
||||
case GL_UNSIGNED_INT:
|
||||
return DataType::Uint32;
|
||||
case GL_FIXED:
|
||||
return DataType::Fixed32;
|
||||
case GL_HALF_FLOAT:
|
||||
return DataType::Float16;
|
||||
case GL_FLOAT:
|
||||
@@ -35,4 +37,4 @@ namespace MobileGL {
|
||||
}
|
||||
}
|
||||
} // namespace MG_Util
|
||||
} // namespace MobileGL
|
||||
} // namespace MobileGL
|
||||
|
||||
@@ -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) {
|
||||
switch (v) {
|
||||
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) {
|
||||
switch (v) {
|
||||
case GL_PACK_ALIGNMENT:
|
||||
|
||||
@@ -14,7 +14,9 @@ namespace MobileGL {
|
||||
namespace MG_Util {
|
||||
BlendFactor ConvertGLEnumToBlendFactor(GLenum value);
|
||||
BlendEquation ConvertGLEnumToBlendEquation(GLenum value);
|
||||
LogicOperation ConvertGLEnumToLogicOperation(GLenum value);
|
||||
DepthTestFunc ConvertGLEnumToDepthTestFunc(GLenum value);
|
||||
StencilOperation ConvertGLEnumToStencilOperation(GLenum value);
|
||||
PixelStoreParam ConvertGLEnumToPixelStoreParam(GLenum value);
|
||||
CullFaceMode ConvertGLEnumToCullFaceMode(GLenum value);
|
||||
FrontFaceMode ConvertGLEnumToFrontFaceMode(GLenum value);
|
||||
|
||||
@@ -14,12 +14,16 @@ namespace MobileGL {
|
||||
TextureTarget ConvertGLEnumToTextureTarget(GLenum target) {
|
||||
switch (target) {
|
||||
case GL_TEXTURE_1D:
|
||||
case GL_PROXY_TEXTURE_1D:
|
||||
return TextureTarget::Texture1D;
|
||||
case GL_TEXTURE_2D:
|
||||
case GL_PROXY_TEXTURE_2D:
|
||||
return TextureTarget::Texture2D;
|
||||
case GL_TEXTURE_3D:
|
||||
case GL_PROXY_TEXTURE_3D:
|
||||
return TextureTarget::Texture3D;
|
||||
case GL_TEXTURE_CUBE_MAP:
|
||||
case GL_PROXY_TEXTURE_CUBE_MAP:
|
||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
|
||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
|
||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
|
||||
@@ -28,18 +32,24 @@ namespace MobileGL {
|
||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
|
||||
return TextureTarget::TextureCubeMap;
|
||||
case GL_TEXTURE_2D_ARRAY:
|
||||
case GL_PROXY_TEXTURE_2D_ARRAY:
|
||||
return TextureTarget::Texture2DArray;
|
||||
case GL_TEXTURE_2D_MULTISAMPLE:
|
||||
case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
|
||||
return TextureTarget::Texture2DMultisample;
|
||||
case GL_TEXTURE_CUBE_MAP_ARRAY:
|
||||
case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
|
||||
return TextureTarget::TextureCubeMapArray;
|
||||
case GL_TEXTURE_BUFFER:
|
||||
return TextureTarget::TextureBuffer;
|
||||
case GL_TEXTURE_1D_ARRAY:
|
||||
case GL_PROXY_TEXTURE_1D_ARRAY:
|
||||
return TextureTarget::Texture1DArray;
|
||||
case GL_TEXTURE_RECTANGLE:
|
||||
case GL_PROXY_TEXTURE_RECTANGLE:
|
||||
return TextureTarget::TextureRectangle;
|
||||
case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
|
||||
case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
|
||||
return TextureTarget::Texture2DMultisampleArray;
|
||||
default:
|
||||
return TextureTarget::Unknown;
|
||||
|
||||
@@ -24,6 +24,8 @@ namespace MobileGL {
|
||||
return GL_INT;
|
||||
case DataType::Uint32:
|
||||
return GL_UNSIGNED_INT;
|
||||
case DataType::Fixed32:
|
||||
return GL_FIXED;
|
||||
case DataType::Float16:
|
||||
return GL_HALF_FLOAT;
|
||||
case DataType::Float32:
|
||||
@@ -35,4 +37,4 @@ namespace MobileGL {
|
||||
}
|
||||
}
|
||||
} // namespace MG_Util
|
||||
} // namespace MobileGL
|
||||
} // namespace MobileGL
|
||||
|
||||
@@ -16,8 +16,9 @@ namespace MobileGL {
|
||||
return GL_DRAW_FRAMEBUFFER;
|
||||
case FramebufferTarget::Read:
|
||||
return GL_READ_FRAMEBUFFER;
|
||||
case FramebufferTarget::Unknown:
|
||||
default:
|
||||
return GL_DRAW_FRAMEBUFFER;
|
||||
return GL_UNKNOWN_MGL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +30,8 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case FramebufferAttachmentType::None:
|
||||
return GL_NONE;
|
||||
case FramebufferAttachmentType::Depth:
|
||||
return GL_DEPTH_ATTACHMENT;
|
||||
case FramebufferAttachmentType::Stencil:
|
||||
@@ -41,8 +44,9 @@ namespace MobileGL {
|
||||
return GL_BACK_LEFT;
|
||||
case FramebufferAttachmentType::BackRight:
|
||||
return GL_BACK_RIGHT;
|
||||
case FramebufferAttachmentType::Unknown:
|
||||
default:
|
||||
return GL_NONE;
|
||||
return GL_UNKNOWN_MGL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,10 +54,11 @@ namespace MobileGL {
|
||||
switch (target) {
|
||||
case RenderbufferTarget::Renderbuffer:
|
||||
return GL_RENDERBUFFER;
|
||||
case RenderbufferTarget::Unknown:
|
||||
default:
|
||||
return GL_RENDERBUFFER;
|
||||
return GL_UNKNOWN_MGL;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace MG_Util
|
||||
} // namespace MobileGL
|
||||
} // namespace MobileGL
|
||||
|
||||
@@ -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) {
|
||||
switch (v) {
|
||||
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) {
|
||||
switch (v) {
|
||||
case PixelStoreParam::PackAlignment:
|
||||
|
||||
@@ -14,7 +14,9 @@ namespace MobileGL {
|
||||
namespace MG_Util {
|
||||
GLenum ConvertBlendFactorToGLEnum(BlendFactor value);
|
||||
GLenum ConvertBlendEquationToGLEnum(BlendEquation value);
|
||||
GLenum ConvertLogicOperationToGLEnum(LogicOperation value);
|
||||
GLenum ConvertDepthTestFuncToGLEnum(DepthTestFunc value);
|
||||
GLenum ConvertStencilOperationToGLEnum(StencilOperation value);
|
||||
GLenum ConvertPixelStoreParamToGLEnum(PixelStoreParam value);
|
||||
GLenum ConvertCullFaceModeToGLEnum(CullFaceMode value);
|
||||
GLenum ConvertFrontFaceModeToGLEnum(FrontFaceMode value);
|
||||
|
||||
@@ -110,6 +110,8 @@ namespace MobileGL {
|
||||
return GL_RGB10;
|
||||
case TextureInternalFormat::RGB12:
|
||||
return GL_RGB12;
|
||||
case TextureInternalFormat::RGB16:
|
||||
return GL_RGB16;
|
||||
case TextureInternalFormat::RGB16Snorm:
|
||||
return GL_RGB16_SNORM;
|
||||
case TextureInternalFormat::RGBA2:
|
||||
@@ -267,6 +269,8 @@ namespace MobileGL {
|
||||
return GL_UNSIGNED_SHORT_5_5_5_1;
|
||||
case TexturePixelDataType::UnsignedShort1555Rev:
|
||||
return GL_UNSIGNED_SHORT_1_5_5_5_REV;
|
||||
case TexturePixelDataType::UnsignedInt8888:
|
||||
return GL_UNSIGNED_INT_8_8_8_8;
|
||||
case TexturePixelDataType::UnsignedInt8888Rev:
|
||||
return GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
case TexturePixelDataType::UnsignedInt1010102:
|
||||
|
||||
@@ -72,6 +72,10 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
String ConvertBufferMappingAccessToString(Flags<BufferMappingAccessBit> access) {
|
||||
if (access == BufferMappingAccessBit::Null) {
|
||||
return "[]";
|
||||
}
|
||||
|
||||
String result = "[";
|
||||
if (access & BufferMappingAccessBit::Read) result += "Read, ";
|
||||
if (access & BufferMappingAccessBit::Write) result += "Write, ";
|
||||
@@ -84,7 +88,7 @@ namespace MobileGL {
|
||||
result.pop_back();
|
||||
result.pop_back();
|
||||
result += "]";
|
||||
return result.empty() ? "[]" : result;
|
||||
return result;
|
||||
}
|
||||
} // namespace MG_Util
|
||||
} // namespace MobileGL
|
||||
} // namespace MobileGL
|
||||
|
||||
@@ -29,6 +29,16 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
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:
|
||||
return "Depth";
|
||||
case FramebufferAttachmentType::Stencil:
|
||||
@@ -49,4 +59,4 @@ namespace MobileGL {
|
||||
}
|
||||
}
|
||||
} // namespace MG_Util
|
||||
} // namespace MobileGL
|
||||
} // namespace MobileGL
|
||||
|
||||
@@ -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) {
|
||||
switch (v) {
|
||||
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) {
|
||||
switch (v) {
|
||||
case PixelStoreParam::PackAlignment:
|
||||
|
||||
@@ -13,7 +13,9 @@
|
||||
namespace MobileGL {
|
||||
namespace MG_Util {
|
||||
String ConvertBlendFactorToString(BlendFactor value);
|
||||
String ConvertLogicOperationToString(LogicOperation value);
|
||||
String ConvertDepthTestFuncToString(DepthTestFunc value);
|
||||
String ConvertStencilOperationToString(StencilOperation value);
|
||||
String ConvertPixelStoreParamToString(PixelStoreParam value);
|
||||
String ConvertCullFaceModeToString(CullFaceMode value);
|
||||
String ConvertFrontFaceModeToString(FrontFaceMode value);
|
||||
|
||||
@@ -110,6 +110,8 @@ namespace MobileGL {
|
||||
return "RGB10";
|
||||
case TextureInternalFormat::RGB12:
|
||||
return "RGB12";
|
||||
case TextureInternalFormat::RGB16:
|
||||
return "RGB16";
|
||||
case TextureInternalFormat::RGB16Snorm:
|
||||
return "RGB16Snorm";
|
||||
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) {
|
||||
switch (v) {
|
||||
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) {
|
||||
switch (v) {
|
||||
case BlendFactor::Zero:
|
||||
|
||||
@@ -14,7 +14,9 @@ namespace MobileGL {
|
||||
namespace MG_Util {
|
||||
VkPrimitiveTopology ConvertPrimitiveModeToVkEnum(GLenum mode);
|
||||
VkCullModeFlags ConvertCullFaceModeToVkEnum(CullFaceMode value, Bool invertClockwise = false);
|
||||
VkLogicOp ConvertLogicOperationToVkEnum(LogicOperation value);
|
||||
VkCompareOp ConvertDepthTestFuncToVkEnum(DepthTestFunc value);
|
||||
VkStencilOp ConvertStencilOperationToVkEnum(StencilOperation value);
|
||||
VkBlendFactor ConvertBlendFactorToVkEnum(BlendFactor value);
|
||||
VkBlendOp ConvertBlendEquationToVkEnum(BlendEquation value);
|
||||
} // namespace MG_Util
|
||||
|
||||
@@ -95,11 +95,13 @@ namespace MobileGL {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
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 +
|
||||
#if MOBILEGL_LOG_ENABLE_STACKTRACE
|
||||
padding +
|
||||
#endif
|
||||
std::string(buffer, n) + "\n";
|
||||
std::string(buffer, messageLength) + "\n";
|
||||
|
||||
#if MOBILEGL_LOG_ENABLE_CONSOLE
|
||||
std::fwrite(out.c_str(), 1, out.size(), stdout);
|
||||
|
||||
@@ -43,6 +43,10 @@ namespace MobileGL {
|
||||
case TextureInternalFormat::DepthComponent24:
|
||||
return 3;
|
||||
|
||||
case TextureInternalFormat::RGB10:
|
||||
case TextureInternalFormat::RGB12:
|
||||
case TextureInternalFormat::RGB16:
|
||||
case TextureInternalFormat::RGB16Snorm:
|
||||
case TextureInternalFormat::RGBA2:
|
||||
case TextureInternalFormat::RGBA4:
|
||||
case TextureInternalFormat::RGB5A1:
|
||||
@@ -54,6 +58,8 @@ namespace MobileGL {
|
||||
case TextureInternalFormat::RGB10A2:
|
||||
case TextureInternalFormat::RGB10A2UI:
|
||||
case TextureInternalFormat::R32F:
|
||||
case TextureInternalFormat::R32I:
|
||||
case TextureInternalFormat::R32UI:
|
||||
case TextureInternalFormat::DepthComponent:
|
||||
case TextureInternalFormat::DepthComponent32:
|
||||
case TextureInternalFormat::DepthComponent32F:
|
||||
@@ -179,6 +185,7 @@ namespace MobileGL {
|
||||
case TextureInternalFormat::RGB10:
|
||||
case TextureInternalFormat::RGB12:
|
||||
case TextureInternalFormat::RGB16:
|
||||
case TextureInternalFormat::RGB16Snorm:
|
||||
case TextureInternalFormat::SRGB8:
|
||||
case TextureInternalFormat::RGB8I:
|
||||
case TextureInternalFormat::RGB8UI:
|
||||
@@ -236,7 +243,6 @@ namespace MobileGL {
|
||||
case TexturePixelDataType::UnsignedInt248:
|
||||
case TexturePixelDataType::Float32UnsignedInt248Rev:
|
||||
return 4;
|
||||
return 4;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -339,6 +345,22 @@ namespace MobileGL {
|
||||
s.Green = 8;
|
||||
s.Blue = 8;
|
||||
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:
|
||||
s.Red = 3;
|
||||
@@ -370,7 +392,6 @@ namespace MobileGL {
|
||||
case TextureInternalFormat::RGBA8UI:
|
||||
case TextureInternalFormat::SRGB8Alpha8:
|
||||
case TextureInternalFormat::RGBA:
|
||||
break;
|
||||
s.Red = 8;
|
||||
s.Green = 8;
|
||||
s.Blue = 8;
|
||||
@@ -385,6 +406,8 @@ namespace MobileGL {
|
||||
break;
|
||||
|
||||
case TextureInternalFormat::R32F:
|
||||
case TextureInternalFormat::R32I:
|
||||
case TextureInternalFormat::R32UI:
|
||||
s.Red = 32;
|
||||
break;
|
||||
case TextureInternalFormat::RG32F:
|
||||
|
||||
@@ -200,6 +200,10 @@ namespace MobileGL {
|
||||
size_t commentStartPos = source.find("/*");
|
||||
while (commentStartPos != String::npos) {
|
||||
size_t commentEndPos = source.find("*/", commentStartPos);
|
||||
if (commentEndPos == String::npos) {
|
||||
source.erase(commentStartPos);
|
||||
break;
|
||||
}
|
||||
// + length of "*/"
|
||||
source = source.replace(commentStartPos, commentEndPos - commentStartPos + 2, "");
|
||||
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, {eps_id}});
|
||||
|
||||
bool isEqualOp =
|
||||
(inst.opcode() == spv::Op::OpFOrdEqual || inst.opcode() == spv::Op::OpFUnordEqual);
|
||||
spv::Op replacementOp = spv::Op::OpNop;
|
||||
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>(
|
||||
context(), isEqualOp ? spv::Op::OpFOrdLessThan : spv::Op::OpFOrdGreaterThanEqual,
|
||||
bool_type_id, context()->TakeNextId(), less_operands));
|
||||
context(), replacementOp, bool_type_id, context()->TakeNextId(), less_operands));
|
||||
|
||||
// 5. Replaces all uses of old insn with new one
|
||||
context()->ReplaceAllUsesWith(inst.result_id(), less_than_inst->result_id());
|
||||
@@ -149,4 +165,4 @@ namespace MobileGL {
|
||||
}
|
||||
} // namespace ShaderTranspiler
|
||||
} // namespace MG_Util
|
||||
} // namespace MobileGL
|
||||
} // namespace MobileGL
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace MobileGL {
|
||||
|
||||
class SpvcSession {
|
||||
public:
|
||||
SpvcSession() {}
|
||||
SpvcSession() = default;
|
||||
|
||||
explicit SpvcSession(const Vector<unsigned int>& spirv,
|
||||
Flags<SessionUsageBit> usage);
|
||||
@@ -97,7 +97,7 @@ namespace MobileGL {
|
||||
spvc_result ParseMetaData();
|
||||
|
||||
private:
|
||||
Flags<SessionUsageBit> usage;
|
||||
Flags<SessionUsageBit> usage{};
|
||||
|
||||
// SPIRV-Cross state (used when Transpile flag is set)
|
||||
spvc_context context = nullptr;
|
||||
@@ -114,4 +114,4 @@ namespace MobileGL {
|
||||
};
|
||||
} // namespace ShaderTranspiler
|
||||
} // namespace MG_Util
|
||||
} // namespace MobileGL
|
||||
} // namespace MobileGL
|
||||
|
||||
@@ -154,8 +154,8 @@ namespace MobileGL::MG_Util::PixelStoreProcessor {
|
||||
MGLOG_D("%s: Swizzle (BGRA)", __func__);
|
||||
// MGLOG_D("%s: pixel0 before = %x", __func__, *((Uint32*)layerDst));
|
||||
ProcessColorSwizzle(layerDst, static_cast<SizeT>(copyWidth),
|
||||
{TextureSwizzleParam::Green, TextureSwizzleParam::Blue,
|
||||
TextureSwizzleParam::Alpha, TextureSwizzleParam::Red});
|
||||
{TextureSwizzleParam::Blue, TextureSwizzleParam::Green,
|
||||
TextureSwizzleParam::Red, TextureSwizzleParam::Alpha});
|
||||
// MGLOG_D("%s: pixel0 after = %x", __func__, *((Uint32*)layerDst));
|
||||
}
|
||||
// else
|
||||
|
||||
@@ -157,6 +157,9 @@ namespace MobileGL::MG_Util::TextureFormatProcessor {
|
||||
case GL_SRGB8:
|
||||
*outFormat = GL_RGB;
|
||||
break;
|
||||
case GL_SRGB8_ALPHA8:
|
||||
*outFormat = GL_RGBA;
|
||||
break;
|
||||
|
||||
// Color sized other
|
||||
case GL_RGB9_E5:
|
||||
@@ -178,6 +181,7 @@ namespace MobileGL::MG_Util::TextureFormatProcessor {
|
||||
break;
|
||||
|
||||
// Depth Stencil
|
||||
case GL_DEPTH24_STENCIL8:
|
||||
case GL_DEPTH32F_STENCIL8:
|
||||
case GL_DEPTH_STENCIL:
|
||||
*outFormat = GL_DEPTH_STENCIL;
|
||||
@@ -298,6 +302,9 @@ namespace MobileGL::MG_Util::TextureFormatProcessor {
|
||||
case GL_SRGB8:
|
||||
*outType = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case GL_SRGB8_ALPHA8:
|
||||
*outType = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
// Color sized other
|
||||
case GL_RGB9_E5:
|
||||
@@ -331,6 +338,9 @@ namespace MobileGL::MG_Util::TextureFormatProcessor {
|
||||
break;
|
||||
|
||||
// Depth Stencil
|
||||
case GL_DEPTH24_STENCIL8:
|
||||
*outType = GL_UNSIGNED_INT_24_8;
|
||||
break;
|
||||
case GL_DEPTH32F_STENCIL8:
|
||||
case GL_DEPTH_STENCIL:
|
||||
*outType = GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
|
||||
@@ -345,4 +355,4 @@ namespace MobileGL::MG_Util::TextureFormatProcessor {
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace MobileGL::MG_Util::TextureFormatProcessor
|
||||
} // namespace MobileGL::MG_Util::TextureFormatProcessor
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace MobileGL {
|
||||
// represents a range of [start, end)
|
||||
struct Range1D {
|
||||
SizeT start = 0;
|
||||
SizeT end = ~0u;
|
||||
SizeT end = ~SizeT(0);
|
||||
|
||||
void Update(SizeT newStart, SizeT newEnd) {
|
||||
MOBILEGL_ASSERT(newStart <= newEnd, "Range1D::Update: newStart (%zu) > newEnd (%zu)", newStart, newEnd);
|
||||
|
||||
+826
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user