diff --git a/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp index 831ecf53..39c515bc 100644 --- a/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp @@ -32,8 +32,7 @@ namespace MobileGL::MG_Backend::DirectGLES { void ClearGLErrors(const MG_External::GLESFunctionsTable& gl) { if (!gl.glGetError) return; - while (gl.glGetError() != GL_NO_ERROR) { - } + while (gl.glGetError() != GL_NO_ERROR) {} } Bool CheckNoGLError(const MG_External::GLESFunctionsTable& gl) { @@ -77,8 +76,7 @@ namespace MobileGL::MG_Backend::DirectGLES { } Bool IsGLESProbeMultisampleTarget(TextureTarget target) { - return target == TextureTarget::Texture2DMultisample || - target == TextureTarget::Texture2DMultisampleArray; + return target == TextureTarget::Texture2DMultisample || target == TextureTarget::Texture2DMultisampleArray; } GLenum GetFramebufferAttachment(TextureInternalFormat format) { @@ -115,8 +113,8 @@ namespace MobileGL::MG_Backend::DirectGLES { GLenum normalizedInternalFormat = glFormat; GLenum imageFormat = GL_RGBA; GLenum imageType = GL_UNSIGNED_BYTE; - MG_Util::TextureFormatProcessor::NormalizePixelFormat( - glFormat, PixelFormatNormalizeOptionBit::None, &normalizedInternalFormat, &imageFormat, &imageType); + MG_Util::TextureFormatProcessor::NormalizePixelFormat(glFormat, PixelFormatNormalizeOptionBit::None, + &normalizedInternalFormat, &imageFormat, &imageType); return imageFormat != GL_RED_INTEGER && imageFormat != GL_RG_INTEGER && imageFormat != GL_RGB_INTEGER && imageFormat != GL_RGBA_INTEGER && !MG_Util::IsDepthFormatInternalFormat(format) && !MG_Util::IsStencilFormatInternalFormat(format); @@ -154,9 +152,9 @@ namespace MobileGL::MG_Backend::DirectGLES { GLESProbeFormatInfo BuildNativeProbeFormatInfo(GLenum requestedInternalFormat) { GLESProbeFormatInfo info; info.InternalFormat = requestedInternalFormat; - MG_Util::TextureFormatProcessor::NormalizePixelFormat( - requestedInternalFormat, PixelFormatNormalizeOptionBit::None, nullptr, &info.ImageFormat, - &info.ImageType); + MG_Util::TextureFormatProcessor::NormalizePixelFormat(requestedInternalFormat, + PixelFormatNormalizeOptionBit::None, nullptr, + &info.ImageFormat, &info.ImageType); return info; } @@ -233,20 +231,16 @@ namespace MobileGL::MG_Backend::DirectGLES { return MG_Util::ConvertGLEnumToString(internalFormat); } - void LogGLESFormatCaveat(TextureInternalFormat logicalFormat, - SizeT targetIndex, + void LogGLESFormatCaveat(TextureInternalFormat logicalFormat, SizeT targetIndex, const GLESProbeFormatInfo& fallbackInfo) { MGLOG_D("Caveat: %s %s not fully supported. Reason: %s. Fallback: %s", GetFormatCapabilityTargetName(targetIndex).c_str(), - MG_Util::ConvertTextureInternalFormatToString(logicalFormat).c_str(), - fallbackInfo.Reason.c_str(), + MG_Util::ConvertTextureInternalFormatToString(logicalFormat).c_str(), fallbackInfo.Reason.c_str(), ConvertFallbackInternalFormatToString(fallbackInfo.InternalFormat).c_str()); } - Bool BuildFallbackProbeFormatInfo(GLenum requestedInternalFormat, - Flags options, - Bool forced, - GLESProbeFormatInfo& outInfo) { + Bool BuildFallbackProbeFormatInfo(GLenum requestedInternalFormat, Flags options, + Bool forced, GLESProbeFormatInfo& outInfo) { const Flags applicableOptions = MG_Util::TextureFormatProcessor::GetApplicablePixelFormatNormalizeOptions(requestedInternalFormat, options); @@ -261,8 +255,7 @@ namespace MobileGL::MG_Backend::DirectGLES { return outInfo.InternalFormat != GL_UNKNOWN_MGL; } - FormatCapabilityFlags BuildTextureCapsFromProbe(TextureInternalFormat logicalFormat, - TextureTarget target, + FormatCapabilityFlags BuildTextureCapsFromProbe(TextureInternalFormat logicalFormat, TextureTarget target, Bool renderable) { FormatCapabilityFlags caps = GetTextureFeatureCaps(logicalFormat, target); if (renderable) { @@ -276,16 +269,12 @@ namespace MobileGL::MG_Backend::DirectGLES { return caps; } - void AddFullFormatCaps(FormatCapabilityCache& cache, - SizeT targetIndex, - SizeT formatIndex, + void AddFullFormatCaps(FormatCapabilityCache& cache, SizeT targetIndex, SizeT formatIndex, FormatCapabilityFlags caps) { cache.FullCaps[targetIndex][formatIndex] |= caps; } - Bool AddCaveatFormatCaps(FormatCapabilityCache& cache, - SizeT targetIndex, - SizeT formatIndex, + Bool AddCaveatFormatCaps(FormatCapabilityCache& cache, SizeT targetIndex, SizeT formatIndex, FormatCapabilityFlags caps) { Bool added = false; for (FormatCapability capability : kReportedFormatCapabilities) { @@ -299,8 +288,7 @@ namespace MobileGL::MG_Backend::DirectGLES { } Int GetGLESFormatMaxSamples(const MG_External::GLESCapabilities& capabilities, - TextureInternalFormat logicalFormat, - GLenum imageFormat) { + TextureInternalFormat logicalFormat, GLenum imageFormat) { const Bool isDepth = MG_Util::IsDepthFormatInternalFormat(logicalFormat); const Bool isStencil = MG_Util::IsStencilFormatInternalFormat(logicalFormat); const Bool isInteger = imageFormat == GL_RED_INTEGER || imageFormat == GL_RG_INTEGER || @@ -314,10 +302,8 @@ namespace MobileGL::MG_Backend::DirectGLES { return capabilities.MaxColorTextureSamples; } - Bool ProbeFramebufferCompletenessForTexture(const MG_External::GLESFunctionsTable& gl, - TextureTarget target, - GLuint texture, - TextureInternalFormat format) { + Bool ProbeFramebufferCompletenessForTexture(const MG_External::GLESFunctionsTable& gl, TextureTarget target, + GLuint texture, TextureInternalFormat format) { GLuint framebuffer = 0; GLint prevFramebuffer = 0; if (!gl.glGenFramebuffers || !gl.glBindFramebuffer || !gl.glCheckFramebufferStatus || @@ -399,9 +385,8 @@ namespace MobileGL::MG_Backend::DirectGLES { return supported; } - Bool ProbeFramebufferCompletenessForRenderbuffer(const MG_External::GLESFunctionsTable& gl, - GLuint renderbuffer, - TextureInternalFormat format) { + Bool ProbeFramebufferCompletenessForRenderbuffer(const MG_External::GLESFunctionsTable& gl, GLuint renderbuffer, + TextureInternalFormat format) { GLuint framebuffer = 0; GLint prevFramebuffer = 0; if (!gl.glGenFramebuffers || !gl.glBindFramebuffer || !gl.glFramebufferRenderbuffer || @@ -468,16 +453,16 @@ namespace MobileGL::MG_Backend::DirectGLES { } break; case TextureTarget::Texture3D: - gl.glTexImage3D(glTarget, 0, static_cast(internalFormat), 2, 2, 2, 0, imageFormat, - imageType, nullptr); + gl.glTexImage3D(glTarget, 0, static_cast(internalFormat), 2, 2, 2, 0, imageFormat, imageType, + nullptr); break; case TextureTarget::Texture2DArray: - gl.glTexImage3D(glTarget, 0, static_cast(internalFormat), 2, 2, 1, 0, imageFormat, - imageType, nullptr); + gl.glTexImage3D(glTarget, 0, static_cast(internalFormat), 2, 2, 1, 0, imageFormat, imageType, + nullptr); break; case TextureTarget::TextureCubeMapArray: - gl.glTexImage3D(glTarget, 0, static_cast(internalFormat), 2, 2, 6, 0, imageFormat, - imageType, nullptr); + gl.glTexImage3D(glTarget, 0, static_cast(internalFormat), 2, 2, 6, 0, imageFormat, imageType, + nullptr); break; default: break; @@ -498,11 +483,8 @@ namespace MobileGL::MG_Backend::DirectGLES { return created; } - Bool ProbeRenderbuffer(const MG_External::GLESFunctionsTable& gl, - GLenum internalFormat, - TextureInternalFormat logicalFormat, - Bool multisample, - Int samples) { + Bool ProbeRenderbuffer(const MG_External::GLESFunctionsTable& gl, GLenum internalFormat, + TextureInternalFormat logicalFormat, Bool multisample, Int samples) { if (!gl.glGenRenderbuffers || !gl.glBindRenderbuffer || !gl.glDeleteRenderbuffers) { return false; } @@ -524,17 +506,16 @@ namespace MobileGL::MG_Backend::DirectGLES { gl.glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, 1, 1); } const Bool created = CheckNoGLError(gl); - const Bool complete = created && ProbeFramebufferCompletenessForRenderbuffer(gl, renderbuffer, logicalFormat); + const Bool complete = + created && ProbeFramebufferCompletenessForRenderbuffer(gl, renderbuffer, logicalFormat); gl.glBindRenderbuffer(GL_RENDERBUFFER, static_cast(prevRenderbuffer)); gl.glDeleteRenderbuffers(1, &renderbuffer); ClearGLErrors(gl); return complete; } - Vector ProbeRenderbufferSampleCounts(const MG_External::GLESFunctionsTable& gl, - GLenum internalFormat, - TextureInternalFormat logicalFormat, - Int maxSamples) { + Vector ProbeRenderbufferSampleCounts(const MG_External::GLESFunctionsTable& gl, GLenum internalFormat, + TextureInternalFormat logicalFormat, Int maxSamples) { Vector sampleCounts; for (Int samples = std::max(maxSamples, 1); samples > 1; samples >>= 1) { if (ProbeRenderbuffer(gl, internalFormat, logicalFormat, true, samples)) { @@ -589,8 +570,8 @@ namespace MobileGL::MG_Backend::DirectGLES { hasForcedFallback = BuildFallbackProbeFormatInfo( requestedInternalFormat, forcedOptions | targetOptions, true, fallbackInfo); if (!hasForcedFallback) { - BuildFallbackProbeFormatInfo(requestedInternalFormat, driverOptions | targetOptions, - false, fallbackInfo); + BuildFallbackProbeFormatInfo(requestedInternalFormat, driverOptions | targetOptions, false, + fallbackInfo); } } @@ -623,9 +604,9 @@ namespace MobileGL::MG_Backend::DirectGLES { ProbeTexture(gl, probeTarget, fallbackInfo.InternalFormat, fallbackInfo.ImageFormat, fallbackInfo.ImageType, logicalFormat, &fallbackRenderable); if (fallbackCreated) { - if (AddCaveatFormatCaps(cache, targetIndex, formatIndex, - BuildTextureCapsFromProbe(logicalFormat, target, - fallbackRenderable))) { + if (AddCaveatFormatCaps( + cache, targetIndex, formatIndex, + BuildTextureCapsFromProbe(logicalFormat, target, fallbackRenderable))) { LogGLESFormatCaveat(logicalFormat, targetIndex, fallbackInfo); } if (IsGLESProbeMultisampleTarget(target)) { @@ -676,7 +657,7 @@ namespace MobileGL::MG_Backend::DirectGLES { .ExtraVendor = Nullopt, // Extra vendor .RendererGLInfo = { - .TargetGLVersion = {3, 3, 0}, // GL target version + .TargetGLVersion = {4, 0, 0}, // GL target version .TargetGLSLVersion = {4, 6, 0}, // Target Shading Language Version // Baseline advertisement (no timer queries / anisotropy yet); reconciled // once the ES capabilities exist, see UpdateAdvertisedCapabilityExtensions. @@ -707,8 +688,7 @@ namespace MobileGL::MG_Backend::DirectGLES { } // namespace void PopulateFormatCapabilities(const MG_External::GLESFunctionsTable& gl, - const MG_External::GLESCapabilities& capabilities, - FormatCapabilityCache& cache) { + const MG_External::GLESCapabilities& capabilities, FormatCapabilityCache& cache) { PopulateFormatCapabilitiesImpl(gl, capabilities, cache); } @@ -772,10 +752,8 @@ namespace MobileGL::MG_Backend::DirectGLES { return false; } - if ((handle.Backend != WindowBackend::Android && - handle.Backend != WindowBackend::X11 && - handle.Backend != WindowBackend::MetalLayer && - handle.Backend != WindowBackend::Win32) || + if ((handle.Backend != WindowBackend::Android && handle.Backend != WindowBackend::X11 && + handle.Backend != WindowBackend::MetalLayer && handle.Backend != WindowBackend::Win32) || !handle.Handle) { MGLOG_E("DirectGLES backend only supports Android, X11, CAMetalLayer, and Win32 native windows"); return false; @@ -894,27 +872,24 @@ namespace MobileGL::MG_Backend::DirectGLES { } Vector BuildAdvertisedExtensions(Bool timerQueriesSupported, Bool anisotropicFilteringSupported) { - Vector extensions = {V_OpenGL30, V_OpenGL31, V_OpenGL32, - V_OpenGL33, E_GL_ARB_draw_buffers_blend, E_GL_ARB_compute_shader, - E_GL_ARB_shader_storage_buffer_object, E_GL_ARB_shader_image_load_store, - E_GL_ARB_program_interface_query, E_GL_ARB_framebuffer_object, - E_GL_EXT_framebuffer_object, E_GL_ARB_depth_texture, E_GL_ARB_buffer_storage, - E_GL_ARB_texture_storage, E_GL_ARB_texture_storage_multisample, - E_GL_ARB_clear_texture, E_GL_ARB_direct_state_access, - E_GL_ARB_multi_draw_indirect, E_GL_ARB_indirect_parameters, - E_GL_ARB_shader_draw_parameters, E_GL_ARB_gpu_shader5, E_GL_ARB_multi_bind, - E_GL_ARB_shading_language_420pack, E_GL_ARB_vertex_attrib_binding, - // Both are core from GL 3.2/3.3 on and implemented here for - // every advertised version, but an app targeting 3.0/3.1 - // only reaches them through the extension string - the CTS - // picks a whole different shader for draw_buffers without - // explicit_attrib_location. DirectVulkan advertises both. - E_GL_ARB_explicit_attrib_location, E_GL_ARB_texture_multisample, - E_GL_ARB_shader_image_size, - // Advertised with GL_NUM_PROGRAM_BINARY_FORMATS = 0, which the - // extension explicitly permits. It is also the only thing that - // exposes glProgramParameteri before GL 4.1. - E_GL_ARB_get_program_binary}; + Vector extensions = { + V_OpenGL30, V_OpenGL31, V_OpenGL32, V_OpenGL33, E_GL_ARB_draw_buffers_blend, E_GL_ARB_compute_shader, + E_GL_ARB_shader_storage_buffer_object, E_GL_ARB_shader_image_load_store, E_GL_ARB_program_interface_query, + E_GL_ARB_framebuffer_object, E_GL_EXT_framebuffer_object, E_GL_ARB_depth_texture, E_GL_ARB_buffer_storage, + E_GL_ARB_texture_storage, E_GL_ARB_texture_storage_multisample, E_GL_ARB_clear_texture, + E_GL_ARB_direct_state_access, E_GL_ARB_multi_draw_indirect, E_GL_ARB_indirect_parameters, + E_GL_ARB_shader_draw_parameters, E_GL_ARB_gpu_shader5, E_GL_ARB_multi_bind, + E_GL_ARB_shading_language_420pack, E_GL_ARB_vertex_attrib_binding, + // Both are core from GL 3.2/3.3 on and implemented here for + // every advertised version, but an app targeting 3.0/3.1 + // only reaches them through the extension string - the CTS + // picks a whole different shader for draw_buffers without + // explicit_attrib_location. DirectVulkan advertises both. + E_GL_ARB_explicit_attrib_location, E_GL_ARB_texture_multisample, E_GL_ARB_shader_image_size, + // Advertised with GL_NUM_PROGRAM_BINARY_FORMATS = 0, which the + // extension explicitly permits. It is also the only thing that + // exposes glProgramParameteri before GL 4.1. + E_GL_ARB_get_program_binary}; // Only advertised when the device driver actually has usable timer queries // (GL_EXT_disjoint_timer_query plus its entry points) and the // MOBILEGL_DISABLE_TIMERQUERY escape hatch is off. @@ -1052,8 +1027,7 @@ namespace MobileGL::MG_Backend::DirectGLES { return m_dynamicParameters; } - void BackendObject_DirectGLES::ApplyGLESCapabilitiesForTesting( - const MG_External::GLESCapabilities& capabilities) { + void BackendObject_DirectGLES::ApplyGLESCapabilitiesForTesting(const MG_External::GLESCapabilities& capabilities) { m_GLESCapabilities = capabilities; UpdateDynamicBackendParameters(); } @@ -1117,8 +1091,7 @@ namespace MobileGL::MG_Backend::DirectGLES { m_dynamicParameters.TextureBufferOffsetAlignment = m_GLESCapabilities.TextureBufferOffsetAlignment; m_dynamicParameters.MaxUniformBufferBindings = m_GLESCapabilities.MaxUniformBufferBindings; m_dynamicParameters.MaxUniformBlockSize = m_GLESCapabilities.MaxUniformBlockSize; - const Int maxSupportedTextureUnits = - static_cast(MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS); + const Int maxSupportedTextureUnits = static_cast(MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS); m_dynamicParameters.MaxImageUnits = std::max(std::min(m_GLESCapabilities.MaxImageUnits, maxSupportedTextureUnits), 0); m_dynamicParameters.MaxCombinedImageUniforms = std::max(m_GLESCapabilities.MaxCombinedImageUniforms, 0); @@ -1126,8 +1099,7 @@ namespace MobileGL::MG_Backend::DirectGLES { return std::min({std::max(stageLimit, 0), m_dynamicParameters.MaxImageUnits, m_dynamicParameters.MaxCombinedImageUniforms}); }; - m_dynamicParameters.MaxVertexImageUniforms = - clampStageImageUniforms(m_GLESCapabilities.MaxVertexImageUniforms); + m_dynamicParameters.MaxVertexImageUniforms = clampStageImageUniforms(m_GLESCapabilities.MaxVertexImageUniforms); m_dynamicParameters.MaxGeometryImageUniforms = clampStageImageUniforms(m_GLESCapabilities.MaxGeometryImageUniforms); m_dynamicParameters.MaxFragmentImageUniforms = @@ -1157,8 +1129,7 @@ namespace MobileGL::MG_Backend::DirectGLES { const Float requiredMaxOffset = 0.5f - std::ldexp(1.0f, -m_GLESCapabilities.FragmentInterpolationOffsetBits); if (m_GLESCapabilities.MaxFragmentInterpolationOffset >= requiredMaxOffset) { - m_dynamicParameters.MaxFragmentInterpolationOffset = - m_GLESCapabilities.MaxFragmentInterpolationOffset; + m_dynamicParameters.MaxFragmentInterpolationOffset = m_GLESCapabilities.MaxFragmentInterpolationOffset; m_dynamicParameters.FragmentInterpolationOffsetBits = m_GLESCapabilities.FragmentInterpolationOffsetBits; } @@ -1167,9 +1138,8 @@ namespace MobileGL::MG_Backend::DirectGLES { m_GLESCapabilities.AliasedLineWidthRangeMax > 1.0f || m_GLESCapabilities.SmoothLineWidthRangeMax > 1.0f; const auto containsAny = [](const String& haystack, std::initializer_list needles) { - return std::any_of(needles.begin(), needles.end(), [&](const char* needle) { - return haystack.find(needle) != String::npos; - }); + return std::any_of(needles.begin(), needles.end(), + [&](const char* needle) { return haystack.find(needle) != String::npos; }); }; const String vendorAndRenderer = m_GLESCapabilities.GLESVendorString + " " + m_GLESCapabilities.GLESRendererString; diff --git a/MobileGL/MG_Backend/DirectVulkan/BackendObject_DirectVulkan.cpp b/MobileGL/MG_Backend/DirectVulkan/BackendObject_DirectVulkan.cpp index 34fc3a2d..eca3f7ac 100644 --- a/MobileGL/MG_Backend/DirectVulkan/BackendObject_DirectVulkan.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/BackendObject_DirectVulkan.cpp @@ -41,13 +41,11 @@ namespace MobileGL::MG_Backend::DirectVulkan { Bool IsLayeredTarget(TextureTarget target) { return target == TextureTarget::Texture3D || target == TextureTarget::Texture1DArray || target == TextureTarget::Texture2DArray || target == TextureTarget::TextureCubeMap || - target == TextureTarget::TextureCubeMapArray || - target == TextureTarget::Texture2DMultisampleArray; + target == TextureTarget::TextureCubeMapArray || target == TextureTarget::Texture2DMultisampleArray; } Bool IsMultisampleTarget(TextureTarget target) { - return target == TextureTarget::Texture2DMultisample || - target == TextureTarget::Texture2DMultisampleArray; + return target == TextureTarget::Texture2DMultisample || target == TextureTarget::Texture2DMultisampleArray; } Bool IsTextureBufferTarget(TextureTarget target) { @@ -59,8 +57,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { GLenum normalizedInternalFormat = glFormat; GLenum imageFormat = GL_RGBA; GLenum imageType = GL_UNSIGNED_BYTE; - MG_Util::TextureFormatProcessor::NormalizePixelFormat( - glFormat, PixelFormatNormalizeOptionBit::None, &normalizedInternalFormat, &imageFormat, &imageType); + MG_Util::TextureFormatProcessor::NormalizePixelFormat(glFormat, PixelFormatNormalizeOptionBit::None, + &normalizedInternalFormat, &imageFormat, &imageType); return imageFormat == GL_RED_INTEGER || imageFormat == GL_RG_INTEGER || imageFormat == GL_RGB_INTEGER || imageFormat == GL_RGBA_INTEGER; } @@ -81,8 +79,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { return caps; } - FormatCapabilityFlags BuildVulkanCaps(TextureInternalFormat logicalFormat, - TextureTarget target, + FormatCapabilityFlags BuildVulkanCaps(TextureInternalFormat logicalFormat, TextureTarget target, VkFormatFeatureFlags features) { FormatCapabilityFlags caps; const Bool isDepth = MG_Util::IsDepthFormatInternalFormat(logicalFormat); @@ -101,8 +98,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { const Bool sampled = (features & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0; const Bool linearFilter = (features & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT) != 0; const Bool colorRenderable = (features & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) != 0; - const Bool depthStencilRenderable = - (features & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0; + const Bool depthStencilRenderable = (features & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0; const Bool renderable = (isDepth || isStencil) ? depthStencilRenderable : colorRenderable; if (sampled || renderable) { @@ -199,21 +195,20 @@ namespace MobileGL::MG_Backend::DirectVulkan { Bool HasNewCaveatFormatCaps(FormatCapabilityFlags nativeCaps, FormatCapabilityFlags fallbackCaps) { for (FormatCapability capability : kReportedFormatCapabilities) { - if (HasFormatCapability(fallbackCaps, capability) && - !HasFormatCapability(nativeCaps, capability)) { + if (HasFormatCapability(fallbackCaps, capability) && !HasFormatCapability(nativeCaps, capability)) { return true; } } return false; } - void LogVulkanFormatCaveat(TextureInternalFormat logicalFormat, - SizeT targetIndex, + void LogVulkanFormatCaveat(TextureInternalFormat logicalFormat, SizeT targetIndex, TextureInternalFormat fallbackFormat) { - MGLOG_D("Caveat: %s %s not fully supported. Reason: native Vulkan format is not fully supported. Fallback: %s", - GetFormatCapabilityTargetName(targetIndex).c_str(), - MG_Util::ConvertTextureInternalFormatToString(logicalFormat).c_str(), - MG_Util::ConvertTextureInternalFormatToString(fallbackFormat).c_str()); + MGLOG_D( + "Caveat: %s %s not fully supported. Reason: native Vulkan format is not fully supported. Fallback: %s", + GetFormatCapabilityTargetName(targetIndex).c_str(), + MG_Util::ConvertTextureInternalFormatToString(logicalFormat).c_str(), + MG_Util::ConvertTextureInternalFormatToString(fallbackFormat).c_str()); } Vector BuildSampleCounts(Int maxSamples) { @@ -257,15 +252,15 @@ namespace MobileGL::MG_Backend::DirectVulkan { for (SizeT targetIndex = 0; targetIndex < kFormatCapabilityTextureTargetCount; ++targetIndex) { const auto target = static_cast(targetIndex); - const VkFormatFeatureFlags nativeFeatures = - IsTextureBufferTarget(target) ? nativeProperties.bufferFeatures - : nativeProperties.optimalTilingFeatures; + const VkFormatFeatureFlags nativeFeatures = IsTextureBufferTarget(target) + ? nativeProperties.bufferFeatures + : nativeProperties.optimalTilingFeatures; FormatCapabilityFlags nativeCaps = BuildVulkanCaps(logicalFormat, target, nativeFeatures); cache.FullCaps[targetIndex][formatIndex] |= nativeCaps; - const VkFormatFeatureFlags fallbackFeatures = - IsTextureBufferTarget(target) ? fallbackProperties.bufferFeatures - : fallbackProperties.optimalTilingFeatures; + const VkFormatFeatureFlags fallbackFeatures = IsTextureBufferTarget(target) + ? fallbackProperties.bufferFeatures + : fallbackProperties.optimalTilingFeatures; FormatCapabilityFlags fallbackCaps = BuildVulkanCaps(logicalFormat, target, fallbackFeatures); if (fallbackFormat != VK_FORMAT_UNDEFINED && fallbackFormat != nativeFormat) { cache.CaveatCaps[targetIndex][formatIndex] |= fallbackCaps; @@ -300,9 +295,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { cache.FullCaps[renderbufferTargetIndex][formatIndex] |= renderbufferCaps; if (fallbackFormat != VK_FORMAT_UNDEFINED && fallbackFormat != nativeFormat) { - FormatCapabilityFlags fallbackRenderbufferCaps = - BuildVulkanCaps(logicalFormat, TextureTarget::Texture2D, - fallbackProperties.optimalTilingFeatures); + FormatCapabilityFlags fallbackRenderbufferCaps = BuildVulkanCaps( + logicalFormat, TextureTarget::Texture2D, fallbackProperties.optimalTilingFeatures); fallbackRenderbufferCaps &= FormatCapability::Creatable; if ((fallbackProperties.optimalTilingFeatures & (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) != @@ -311,8 +305,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { fallbackRenderbufferCaps |= FormatCapability::MultisampleRenderbuffer; } cache.CaveatCaps[renderbufferTargetIndex][formatIndex] |= fallbackRenderbufferCaps; - if (fallbackLogicalFormat && - HasNewCaveatFormatCaps(renderbufferCaps, fallbackRenderbufferCaps)) { + if (fallbackLogicalFormat && HasNewCaveatFormatCaps(renderbufferCaps, fallbackRenderbufferCaps)) { LogVulkanFormatCaveat(logicalFormat, renderbufferTargetIndex, *fallbackLogicalFormat); } } @@ -329,14 +322,13 @@ namespace MobileGL::MG_Backend::DirectVulkan { void PopulateFormatCapabilities(VkPhysicalDevice physicalDevice, PFN_vkGetPhysicalDeviceFormatProperties getFormatProperties, - const MG_External::VulkanCapabilities& capabilities, - FormatCapabilityCache& cache) { + const MG_External::VulkanCapabilities& capabilities, FormatCapabilityCache& cache) { PopulateFormatCapabilitiesImpl(physicalDevice, getFormatProperties, capabilities, cache); } BackendObject_DirectVulkan::~BackendObject_DirectVulkan() = default; - BackendObject_DirectVulkan::BackendObject_DirectVulkan(): m_rendererInfo{GetRendererIdentity()} {} + BackendObject_DirectVulkan::BackendObject_DirectVulkan() : m_rendererInfo{GetRendererIdentity()} {} Bool BackendObject_DirectVulkan::InitWindowSurface() { if (!m_windowHandle.Handle) { @@ -410,10 +402,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { MGLOG_E("DirectVulkan backend not initialized"); return false; } - if (!handle.Handle || (handle.Backend != WindowBackend::Android && - handle.Backend != WindowBackend::X11 && - handle.Backend != WindowBackend::MetalLayer && - handle.Backend != WindowBackend::Win32)) { + if (!handle.Handle || (handle.Backend != WindowBackend::Android && handle.Backend != WindowBackend::X11 && + handle.Backend != WindowBackend::MetalLayer && handle.Backend != WindowBackend::Win32)) { MGLOG_E("DirectVulkan backend only supports Android, X11, CAMetalLayer, and Win32 native windows"); return false; } @@ -504,37 +494,31 @@ namespace MobileGL::MG_Backend::DirectVulkan { .RendererName = "Magma", .BackendName = "Direct (Vulkan)", .ExtraVendor = Nullopt, - .RendererGLInfo = - { - .TargetGLVersion = {3, 3, 0}, - .TargetGLSLVersion = {4, 6, 0}, - // Baseline advertisement (no shader subgroup, no timer queries); a - // live backend reconciles its copy in UpdateAdvertisedExtensions. - .Extensions = BuildAdvertisedExtensions(false, false, false), - .IsCompatibilityProfile = false - }, + .RendererGLInfo = {.TargetGLVersion = {4, 0, 0}, + .TargetGLSLVersion = {4, 6, 0}, + // Baseline advertisement (no shader subgroup, no timer queries); a + // live backend reconciles its copy in UpdateAdvertisedExtensions. + .Extensions = BuildAdvertisedExtensions(false, false, false), + .IsCompatibilityProfile = false}, .StaticBackendCapability = {.AllowVSOnlyPrograms = false}}; return rendererInfo; } Vector BuildAdvertisedExtensions(Bool shaderSubgroupSupported, Bool timerQueriesSupported, Bool anisotropicFilteringSupported) { - Vector extensions = {V_OpenGL30, V_OpenGL31, V_OpenGL32, - V_OpenGL33, E_GL_ARB_draw_buffers_blend, E_GL_ARB_compute_shader, - E_GL_ARB_shader_storage_buffer_object, E_GL_ARB_shader_image_load_store, - E_GL_ARB_program_interface_query, E_GL_ARB_framebuffer_object, - E_GL_ARB_multi_draw_indirect, E_GL_ARB_indirect_parameters, - E_GL_EXT_framebuffer_object, E_GL_ARB_depth_texture, E_GL_ARB_buffer_storage, - E_GL_ARB_texture_storage, E_GL_ARB_texture_storage_multisample, - E_GL_ARB_texture_multisample, E_GL_ARB_clear_texture, E_GL_ARB_direct_state_access, - E_GL_ARB_shader_draw_parameters, E_GL_ARB_gpu_shader_int64, E_GL_KHR_debug, - E_GL_ARB_gpu_shader5, E_GL_ARB_multi_bind, E_GL_ARB_shading_language_420pack, - E_GL_ARB_vertex_attrib_binding, E_GL_ARB_shader_image_size, - E_GL_ARB_explicit_attrib_location, - // Advertised with GL_NUM_PROGRAM_BINARY_FORMATS = 0, which the - // extension explicitly permits. It is also the only thing that - // exposes glProgramParameteri before GL 4.1. - E_GL_ARB_get_program_binary}; + Vector extensions = { + V_OpenGL30, V_OpenGL31, V_OpenGL32, V_OpenGL33, E_GL_ARB_draw_buffers_blend, E_GL_ARB_compute_shader, + E_GL_ARB_shader_storage_buffer_object, E_GL_ARB_shader_image_load_store, E_GL_ARB_program_interface_query, + E_GL_ARB_framebuffer_object, E_GL_ARB_multi_draw_indirect, E_GL_ARB_indirect_parameters, + E_GL_EXT_framebuffer_object, E_GL_ARB_depth_texture, E_GL_ARB_buffer_storage, E_GL_ARB_texture_storage, + E_GL_ARB_texture_storage_multisample, E_GL_ARB_texture_multisample, E_GL_ARB_clear_texture, + E_GL_ARB_direct_state_access, E_GL_ARB_shader_draw_parameters, E_GL_ARB_gpu_shader_int64, E_GL_KHR_debug, + E_GL_ARB_gpu_shader5, E_GL_ARB_multi_bind, E_GL_ARB_shading_language_420pack, + E_GL_ARB_vertex_attrib_binding, E_GL_ARB_shader_image_size, E_GL_ARB_explicit_attrib_location, + // Advertised with GL_NUM_PROGRAM_BINARY_FORMATS = 0, which the + // extension explicitly permits. It is also the only thing that + // exposes glProgramParameteri before GL 4.1. + E_GL_ARB_get_program_binary}; if (shaderSubgroupSupported && !MG_Config::Features.DisableSubgroup) { extensions.push_back(E_GL_KHR_shader_subgroup); } @@ -731,7 +715,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { // rather than a maximum the sampler manager will never apply. m_dynamicParameters.MaxTextureMaxAnisotropy = (pVulkanRenderer && pVulkanRenderer->IsSamplerAnisotropySupported()) ? m_vulkanCaps.MaxSamplerAnisotropy - : 1.0f; + : 1.0f; m_dynamicParameters.SmoothLineWidthRangeMin = m_vulkanCaps.SmoothLineWidthRangeMin; m_dynamicParameters.SmoothLineWidthRangeMax = m_vulkanCaps.SmoothLineWidthRangeMax; m_dynamicParameters.SmoothLineWidthGranularity = m_vulkanCaps.SmoothLineWidthGranularity; @@ -752,8 +736,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { m_dynamicParameters.MaxIntegerSamples = m_vulkanCaps.MaxIntegerSamples; m_dynamicParameters.MaxSamples = m_vulkanCaps.MaxSamples; m_dynamicParameters.MaxSampleMaskWords = m_vulkanCaps.MaxSampleMaskWords; - const Int maxSupportedTextureUnits = - static_cast(MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS); + const Int maxSupportedTextureUnits = static_cast(MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS); // GL_MAX_TEXTURE_IMAGE_UNITS is a *per-stage* sampler limit. Adreno/Qualcomm report a huge // maxPerStageDescriptorSampledImages (descriptor-indexing scale), so clamping it only to our // combined array capacity (192) still advertises 192 per stage. Host code treats this value as @@ -763,8 +746,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { // limits while keeping the combined limit at our texture-unit array capacity. constexpr Int maxPerStageTextureUnits = static_cast(MG_State::GLState::TextureState::MAX_PER_STAGE_TEXTURE_IMAGE_UNITS); - m_dynamicParameters.MaxTextureImageUnits = - std::min(m_vulkanCaps.MaxTextureImageUnits, maxPerStageTextureUnits); + m_dynamicParameters.MaxTextureImageUnits = std::min(m_vulkanCaps.MaxTextureImageUnits, maxPerStageTextureUnits); m_dynamicParameters.MaxVertexTextureImageUnits = std::min(m_vulkanCaps.MaxVertexTextureImageUnits, maxPerStageTextureUnits); m_dynamicParameters.MaxComputeTextureImageUnits = @@ -773,9 +755,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { std::min(m_vulkanCaps.MaxCombinedTextureImageUnits, maxSupportedTextureUnits); // Never advertise more attributes than the state layer can store: the current-value array and // the Uint32 attribute masks the draw path passes around are both bounded by MAX_VERTEX_ATTRIBS. - m_dynamicParameters.MaxVertexAttribs = - std::min(m_vulkanCaps.MaxVertexAttribs, - static_cast(MG_State::GLState::VertexArrayObject::MAX_VERTEX_ATTRIBS)); + m_dynamicParameters.MaxVertexAttribs = std::min( + m_vulkanCaps.MaxVertexAttribs, static_cast(MG_State::GLState::VertexArrayObject::MAX_VERTEX_ATTRIBS)); m_dynamicParameters.MaxComputeShaderStorageBlocks = m_vulkanCaps.MaxComputeShaderStorageBlocks; m_dynamicParameters.MaxCombinedShaderStorageBlocks = m_vulkanCaps.MaxCombinedShaderStorageBlocks; m_dynamicParameters.MaxComputeUniformBlocks = m_vulkanCaps.MaxComputeUniformBlocks; @@ -785,8 +766,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { m_dynamicParameters.TextureBufferOffsetAlignment = m_vulkanCaps.TextureBufferOffsetAlignment; m_dynamicParameters.MaxUniformBufferBindings = m_vulkanCaps.MaxUniformBufferBindings; m_dynamicParameters.MaxUniformBlockSize = m_vulkanCaps.MaxUniformBlockSize; - m_dynamicParameters.MaxImageUnits = - std::max(std::min(m_vulkanCaps.MaxImageUnits, maxSupportedTextureUnits), 0); + m_dynamicParameters.MaxImageUnits = std::max(std::min(m_vulkanCaps.MaxImageUnits, maxSupportedTextureUnits), 0); m_dynamicParameters.MaxCombinedImageUniforms = std::max(m_vulkanCaps.MaxCombinedImageUniforms, 0); const Int maxPerStageImageUniforms = std::min(m_dynamicParameters.MaxImageUnits, m_dynamicParameters.MaxCombinedImageUniforms); @@ -803,8 +783,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { m_vulkanCaps.SupportsFragmentStoresAndAtomics ? maxPerStageImageUniforms : 0; m_dynamicParameters.MaxComputeImageUniforms = std::min(std::max(m_vulkanCaps.MaxComputeImageUniforms, 0), maxPerStageImageUniforms); - const Int maxSupportedDrawBuffers = - static_cast(MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS); + const Int maxSupportedDrawBuffers = static_cast(MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS); m_dynamicParameters.MaxDrawBuffers = std::min(m_vulkanCaps.MaxDrawBuffers, maxSupportedDrawBuffers); m_dynamicParameters.MaxColorAttachments = std::min(m_vulkanCaps.MaxColorAttachments, maxSupportedDrawBuffers); m_dynamicParameters.MaxClipDistances = m_vulkanCaps.MaxClipDistances; @@ -823,12 +802,10 @@ namespace MobileGL::MG_Backend::DirectVulkan { m_dynamicParameters.FragmentInterpolationOffsetBits = 4; if (m_vulkanCaps.FragmentInterpolationOffsetBits >= 4 && std::isfinite(m_vulkanCaps.MaxFragmentInterpolationOffset)) { - const Float requiredMaxOffset = - 0.5f - std::ldexp(1.0f, -m_vulkanCaps.FragmentInterpolationOffsetBits); + const Float requiredMaxOffset = 0.5f - std::ldexp(1.0f, -m_vulkanCaps.FragmentInterpolationOffsetBits); if (m_vulkanCaps.MaxFragmentInterpolationOffset >= requiredMaxOffset) { m_dynamicParameters.MaxFragmentInterpolationOffset = m_vulkanCaps.MaxFragmentInterpolationOffset; - m_dynamicParameters.FragmentInterpolationOffsetBits = - m_vulkanCaps.FragmentInterpolationOffsetBits; + m_dynamicParameters.FragmentInterpolationOffsetBits = m_vulkanCaps.FragmentInterpolationOffsetBits; } } m_dynamicParameters.SupportsWideLines = m_vulkanCaps.SupportsWideLines; @@ -837,7 +814,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { if (m_vulkanCaps.SupportsShaderSubgroup) { m_dynamicParameters.SubgroupSize = m_vulkanCaps.SubgroupSize; m_dynamicParameters.SubgroupSupportedStages = mapShaderStages(m_vulkanCaps.SubgroupSupportedStages); - m_dynamicParameters.SubgroupSupportedFeatures = mapSubgroupFeatures(m_vulkanCaps.SubgroupSupportedOperations); + m_dynamicParameters.SubgroupSupportedFeatures = + mapSubgroupFeatures(m_vulkanCaps.SubgroupSupportedOperations); m_dynamicParameters.SubgroupQuadOperationsInAllStages = m_vulkanCaps.SubgroupQuadOperationsInAllStages; } else { m_dynamicParameters.SubgroupSize = 0; @@ -847,8 +825,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { } if (m_dynamicParameters.MaxShaderStorageBlockSize != m_vulkanCaps.MaxShaderStorageBlockSize) { MGLOG_I("DirectVulkan: clamped GL_MAX_SHADER_STORAGE_BLOCK_SIZE from %zu to %zu", - m_vulkanCaps.MaxShaderStorageBlockSize, - m_dynamicParameters.MaxShaderStorageBlockSize); + m_vulkanCaps.MaxShaderStorageBlockSize, m_dynamicParameters.MaxShaderStorageBlockSize); } switch (m_vulkanCaps.VendorId) { case 0x5143u: // VK_VENDOR_ID: Qualcomm diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkSamplerManager.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkSamplerManager.cpp index b4127289..93b26ba9 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkSamplerManager.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkSamplerManager.cpp @@ -164,7 +164,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { XXHASH_VERIFY(XXH64_update(m_hashState, &maxAnisotropy, sizeof(maxAnisotropy))); const auto compareMode = sampler.GetCompareMode(); XXHASH_VERIFY(XXH64_update(m_hashState, &compareMode, sizeof(compareMode))); - const auto compareFunc = ResolveCompareFunc(sampler, texture); + const auto compareFunc = sampler.GetSamplerCompareFunc(); XXHASH_VERIFY(XXH64_update(m_hashState, &compareFunc, sizeof(compareFunc))); const auto borderColor = ResolveVkBorderColor(sampler, texture); XXHASH_VERIFY(XXH64_update(m_hashState, &borderColor, sizeof(borderColor))); @@ -207,7 +207,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { samplerInfo.anisotropyEnable = maxAnisotropy > 1.0f ? VK_TRUE : VK_FALSE; samplerInfo.maxAnisotropy = maxAnisotropy; samplerInfo.compareEnable = sampler.GetCompareMode() == SamplerCompareMode::CompareToTexture ? VK_TRUE : VK_FALSE; - samplerInfo.compareOp = ToVkCompareOp(ResolveCompareFunc(sampler, texture)); + samplerInfo.compareOp = ToVkCompareOp(sampler.GetSamplerCompareFunc()); // Must match BuildSamplerKey's resolution exactly. samplerInfo.maxLod = ResolveSingleLevelMaxLod(sampler, singleLevelView); samplerInfo.minLod = ResolveEffectiveMinLod(sampler, samplerInfo.maxLod); @@ -281,17 +281,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { } } - SamplerCompareFunc VkSamplerManager::ResolveCompareFunc(const MG_State::GLState::SamplerObject& sampler, - const MG_State::GLState::ITextureObject& texture) { - const auto compareFunc = sampler.GetSamplerCompareFunc(); - if (sampler.GetCompareMode() == SamplerCompareMode::CompareToTexture && - IsDepthTextureFormat(texture.GetFormat()) && compareFunc == SamplerCompareFunc::Always) { - return SamplerCompareFunc::LessEqual; - } - - return compareFunc; - } - VkBorderColor VkSamplerManager::ResolveVkBorderColor(const MG_State::GLState::SamplerObject& sampler, const MG_State::GLState::ITextureObject& texture) { if (!UsesBorderColor(sampler)) { diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkSamplerManager.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkSamplerManager.h index 8cbedff0..c00484d0 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkSamplerManager.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkSamplerManager.h @@ -69,8 +69,6 @@ private: static VkSamplerMipmapMode ToVkMipmapMode(SamplerMipmapMode mode); static VkSamplerAddressMode ToVkAddressMode(SamplerWrapMode mode); static VkCompareOp ToVkCompareOp(SamplerCompareFunc func); - static SamplerCompareFunc ResolveCompareFunc(const MG_State::GLState::SamplerObject& sampler, - const MG_State::GLState::ITextureObject& texture); static VkBorderColor ResolveVkBorderColor(const MG_State::GLState::SamplerObject& sampler, const MG_State::GLState::ITextureObject& texture); // The anisotropy Vulkan will actually apply: 1.0 (i.e. disabled) unless the feature is on and diff --git a/MobileGL/MG_State/GLState/SamplerState/SamplerObject.h b/MobileGL/MG_State/GLState/SamplerState/SamplerObject.h index 54352396..0007f03e 100644 --- a/MobileGL/MG_State/GLState/SamplerState/SamplerObject.h +++ b/MobileGL/MG_State/GLState/SamplerState/SamplerObject.h @@ -66,7 +66,9 @@ namespace MobileGL { Float maxLod = 1000.0f; Float lodBias = 0.0f; Float maxAnisotropy = 1.0f; - SamplerCompareFunc compareFunc = SamplerCompareFunc::Always; + // GL 4.6 core table 23.18 / GLES 3.2 table 21.16: TEXTURE_COMPARE_FUNC starts at LEQUAL, + // for both sampler objects and the sampler state a texture object carries. + SamplerCompareFunc compareFunc = SamplerCompareFunc::LessEqual; SamplerCompareMode compareMode = SamplerCompareMode::None; };