mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[Feat] (GL): advertise the 4.x-core extension batch and ARB_tessellation_shader where the device has tessellation
This commit is contained in:
@@ -309,6 +309,15 @@ namespace MobileGL {
|
||||
void (*SetSwapInterval)(Int interval);
|
||||
};
|
||||
|
||||
// Device features that decide whether an extension string may be advertised, beyond the
|
||||
// per-backend positional flags of BuildAdvertisedExtensions. Each is the PROBED driver
|
||||
// capability (an ES version / extension on DirectGLES, a VkPhysicalDeviceFeatures bit on
|
||||
// DirectVulkan), never a vendor guess. Defaults describe the no-device case.
|
||||
struct AdvertisedFeatureSupport {
|
||||
// ES 3.2 or GL_EXT_tessellation_shader; VkPhysicalDeviceFeatures::tessellationShader.
|
||||
Bool TessellationShader = false;
|
||||
};
|
||||
|
||||
// Coarse GPU vendor identity for gating device-specific quirks. Detected from the
|
||||
// Vulkan physical-device vendorID or the GLES GL_VENDOR/GL_RENDERER strings; stays
|
||||
// Unknown when detection is inconclusive, in which case auto-gated quirks stay off.
|
||||
|
||||
@@ -841,7 +841,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
AreTimerQueriesSupported(), capabilities.SupportsTextureFilterAnisotropy,
|
||||
capabilities.SupportsDrawIndirect,
|
||||
capabilities.SupportsDrawIndirect && capabilities.SupportsBaseInstance,
|
||||
capabilities.SupportsTextureView, capabilities.SupportsTextureCubeMapArray);
|
||||
capabilities.SupportsTextureView, capabilities.SupportsTextureCubeMapArray,
|
||||
AdvertisedFeatureSupport{.TessellationShader = capabilities.SupportsTessellationShader});
|
||||
// Exactly what InitCapabilities forwards into the dynamic parameters: the base
|
||||
// extension and _primitive when the driver has them, _attachment not yet.
|
||||
auto& extensions = MutableRendererInfo().RendererGLInfo.Extensions;
|
||||
@@ -1383,7 +1384,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
Vector<GLExtension> BuildAdvertisedExtensions(Bool timerQueriesSupported, Bool anisotropicFilteringSupported,
|
||||
Bool drawIndirectSupported,
|
||||
Bool nonZeroIndirectBaseInstanceSupported,
|
||||
Bool textureViewSupported, Bool cubeMapArraySupported) {
|
||||
Bool textureViewSupported, Bool cubeMapArraySupported,
|
||||
const AdvertisedFeatureSupport& features) {
|
||||
Vector<GLExtension> extensions = {
|
||||
// The version tokens have to reach the version the backend actually claims:
|
||||
// TargetGLVersion is {4,6,0}, and a list that stopped at OpenGL40 told an
|
||||
@@ -1494,10 +1496,33 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// glDepthRangeArrayv / glDepthRangeIndexed / glGetFloati_v / glGetDoublei_v, over the
|
||||
// 16 viewports GL_MAX_VIEWPORTS reports and the per-viewport routing emulation.
|
||||
E_GL_ARB_viewport_array,
|
||||
// Core in the 4.x versions this backend already claims, and named so a context of an
|
||||
// older requested version reaches the same, already-implemented surface (the conformance
|
||||
// suite gates its GL 3.x runs of these on the string alone):
|
||||
// - transform feedback objects, pause/resume and glDrawTransformFeedback (4.0);
|
||||
E_GL_ARB_transform_feedback2,
|
||||
// - multiple capture buffers per stream, gl_SkipComponents / gl_NextBuffer, the
|
||||
// indexed queries and glDrawTransformFeedbackStream (4.0);
|
||||
E_GL_ARB_transform_feedback3,
|
||||
// - GL_RGB10_A2UI (3.3), GL_RGB9_E5 (3.0) and the integer colour formats (3.0);
|
||||
E_GL_ARB_texture_rgb10_a2ui, E_GL_EXT_texture_shared_exponent, E_GL_EXT_texture_integer,
|
||||
// - the eleven pipeline-statistics query targets (4.6). Accepted by glBeginQuery and
|
||||
// answered with GL_QUERY_COUNTER_BITS = 0, the spec's own "this counter is not
|
||||
// instrumented" signal (see IsPipelineStatisticsQueryTarget in GL_Query.cpp);
|
||||
E_GL_ARB_pipeline_statistics_query,
|
||||
// - mix() over integer and boolean vectors in GLSL below 4.50. The frontend compiles it
|
||||
// to OpSelect, which the backend prints back as a core boolean mix.
|
||||
E_GL_EXT_shader_integer_mix,
|
||||
// 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};
|
||||
// Tessellation is core from GL 4.0, but on the host it is ES 3.2 or
|
||||
// GL_EXT_tessellation_shader, so the string follows the driver. GL_Query also reads it to
|
||||
// open the two tessellation pipeline-statistics targets.
|
||||
if (features.TessellationShader) {
|
||||
extensions.push_back(E_GL_ARB_tessellation_shader);
|
||||
}
|
||||
// Minecraft 26.3 checks this prerequisite before it even considers
|
||||
// GL_ARB_multi_draw_indirect. ES 3.1 supplies both single-draw entry points; the loader
|
||||
// folds the version and pointer checks into SupportsDrawIndirect.
|
||||
|
||||
@@ -114,12 +114,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
|
||||
// The full OpenGL extension list Espryt advertises (glGetString(GL_EXTENSIONS))
|
||||
// for a device whose timer queries / anisotropic filtering / native indirect draws /
|
||||
// non-zero indirect baseInstance semantics / EXT-OES texture views are (or are not) usable.
|
||||
// The MOBILEGL_DISABLE_TIMERQUERY escape hatch is applied inside.
|
||||
// non-zero indirect baseInstance semantics / EXT-OES texture views are (or are not) usable,
|
||||
// plus the feature set in `features`. The MOBILEGL_DISABLE_TIMERQUERY escape hatch is applied
|
||||
// inside.
|
||||
Vector<GLExtension> BuildAdvertisedExtensions(Bool timerQueriesSupported, Bool anisotropicFilteringSupported,
|
||||
Bool drawIndirectSupported,
|
||||
Bool nonZeroIndirectBaseInstanceSupported,
|
||||
Bool textureViewSupported, Bool cubeMapArraySupported);
|
||||
Bool textureViewSupported, Bool cubeMapArraySupported,
|
||||
const AdvertisedFeatureSupport& features = {});
|
||||
|
||||
// Format: <OpenGL ES Renderer>, OpenGL ES <Major>.<Minor> — the exact string an
|
||||
// initialized backend returns from GetBackendAPIVersionString (and that ends up
|
||||
|
||||
@@ -792,7 +792,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
Vector<GLExtension> BuildAdvertisedExtensions(Bool shaderSubgroupSupported, Bool timerQueriesSupported,
|
||||
Bool anisotropicFilteringSupported,
|
||||
Bool nonZeroIndirectBaseInstanceSupported,
|
||||
Bool cubeMapArraySupported) {
|
||||
Bool cubeMapArraySupported,
|
||||
const AdvertisedFeatureSupport& features) {
|
||||
Vector<GLExtension> extensions = {
|
||||
// The version tokens have to reach the version the backend actually claims:
|
||||
// TargetGLVersion is {4,6,0}, and a list that stopped at OpenGL40 told an
|
||||
@@ -898,10 +899,32 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
// glDepthRangeArrayv / glDepthRangeIndexed / glGetFloati_v / glGetDoublei_v, over the
|
||||
// 16 viewports GL_MAX_VIEWPORTS reports.
|
||||
E_GL_ARB_viewport_array,
|
||||
// Core in the 4.x versions this backend already claims, and named so a context of an
|
||||
// older requested version reaches the same, already-implemented surface (the conformance
|
||||
// suite gates its GL 3.x runs of these on the string alone):
|
||||
// - transform feedback objects, pause/resume and glDrawTransformFeedback (4.0);
|
||||
E_GL_ARB_transform_feedback2,
|
||||
// - multiple capture buffers per stream, gl_SkipComponents / gl_NextBuffer, the
|
||||
// indexed queries and glDrawTransformFeedbackStream (4.0);
|
||||
E_GL_ARB_transform_feedback3,
|
||||
// - GL_RGB10_A2UI (3.3), GL_RGB9_E5 (3.0) and the integer colour formats (3.0);
|
||||
E_GL_ARB_texture_rgb10_a2ui, E_GL_EXT_texture_shared_exponent, E_GL_EXT_texture_integer,
|
||||
// - the eleven pipeline-statistics query targets (4.6). Accepted by glBeginQuery and
|
||||
// answered with GL_QUERY_COUNTER_BITS = 0, the spec's own "this counter is not
|
||||
// instrumented" signal (see IsPipelineStatisticsQueryTarget in GL_Query.cpp);
|
||||
E_GL_ARB_pipeline_statistics_query,
|
||||
// - mix() over integer and boolean vectors in GLSL below 4.50. The frontend compiles it
|
||||
// to OpSelect, which SPIR-V consumes directly.
|
||||
E_GL_EXT_shader_integer_mix,
|
||||
// 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};
|
||||
// Follows the tessellationShader device feature; GL_Query also reads the string to open
|
||||
// the two tessellation pipeline-statistics targets.
|
||||
if (features.TessellationShader) {
|
||||
extensions.push_back(E_GL_ARB_tessellation_shader);
|
||||
}
|
||||
// Vulkan's drawIndirectFirstInstance feature is optional. Direct base-instance calls work
|
||||
// without it, but ARB_base_instance also promises non-zero firstInstance in GPU indirect
|
||||
// commands; the renderer supplies true only when that word is legal and gl_InstanceID can
|
||||
@@ -1082,7 +1105,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
subgroupSupportAdvertised, pVulkanRenderer && pVulkanRenderer->IsTimerQuerySupported(),
|
||||
pVulkanRenderer && pVulkanRenderer->IsSamplerAnisotropySupported(),
|
||||
pVulkanRenderer && pVulkanRenderer->IsNonZeroIndirectBaseInstanceSupported(),
|
||||
m_vulkanCaps.SupportsImageCubeArray);
|
||||
m_vulkanCaps.SupportsImageCubeArray,
|
||||
AdvertisedFeatureSupport{.TessellationShader = m_vulkanCaps.SupportsTessellationShader});
|
||||
// GL_EXT_fragment_shading_rate rides on VK_KHR_fragment_shading_rate's pipeline rate, and
|
||||
// its _primitive companion on the primitive rate; both only when the renderer enabled them.
|
||||
// _attachment is not advertised: no framebuffer carries a rate attachment to this backend.
|
||||
|
||||
@@ -115,7 +115,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
Vector<GLExtension> BuildAdvertisedExtensions(Bool shaderSubgroupSupported, Bool timerQueriesSupported,
|
||||
Bool anisotropicFilteringSupported,
|
||||
Bool nonZeroIndirectBaseInstanceSupported,
|
||||
Bool cubeMapArraySupported);
|
||||
Bool cubeMapArraySupported,
|
||||
const AdvertisedFeatureSupport& features = {});
|
||||
|
||||
// Format: <GPU Name>, Vulkan <Vulkan Version>, Driver <Driver Version> — the exact
|
||||
// string an initialized backend returns from GetBackendAPIVersionString (and that
|
||||
|
||||
@@ -1244,6 +1244,78 @@ TEST(CorePlumbingAdvertisement, IsUnconditionalAndIdenticalOnBothBackends) {
|
||||
}
|
||||
}
|
||||
|
||||
// Strings for functionality that is core in the 4.x versions MobileGL claims, named so contexts of
|
||||
// an older requested version (the conformance suite's GL 3.x runs gate on the string alone) reach
|
||||
// the same surface. Unconditional on both backends; only the tessellation string follows a probed
|
||||
// device capability.
|
||||
TEST(CoreSurfaceAdvertisement, BatchIsUnconditionalAndTessellationFollowsTheDevice) {
|
||||
const auto contains = [](const MobileGL::Vector<MobileGL::GLExtension>& extensions,
|
||||
MobileGL::GLExtension wanted) {
|
||||
return std::find(extensions.begin(), extensions.end(), wanted) != extensions.end();
|
||||
};
|
||||
const MobileGL::GLExtension expected[] = {
|
||||
MobileGL::E_GL_ARB_transform_feedback2, MobileGL::E_GL_ARB_transform_feedback3,
|
||||
MobileGL::E_GL_ARB_texture_rgb10_a2ui, MobileGL::E_GL_EXT_texture_shared_exponent,
|
||||
MobileGL::E_GL_EXT_texture_integer, MobileGL::E_GL_ARB_pipeline_statistics_query,
|
||||
MobileGL::E_GL_EXT_shader_integer_mix};
|
||||
|
||||
const auto es = MobileGL::MG_Backend::DirectGLES::BuildAdvertisedExtensions(false, false, false, false, false,
|
||||
false);
|
||||
const auto vk = MobileGL::MG_Backend::DirectVulkan::BuildAdvertisedExtensions(false, false, false, false, false);
|
||||
for (const auto extension : expected) {
|
||||
EXPECT_TRUE(contains(es, extension)) << "DirectGLES does not advertise extension " << extension;
|
||||
EXPECT_TRUE(contains(vk, extension)) << "DirectVulkan does not advertise extension " << extension;
|
||||
}
|
||||
// Withheld until shaders can actually use the gl_FragCoord layout qualifiers it adds.
|
||||
EXPECT_FALSE(contains(es, MobileGL::E_GL_ARB_fragment_coord_conventions));
|
||||
EXPECT_FALSE(contains(vk, MobileGL::E_GL_ARB_fragment_coord_conventions));
|
||||
|
||||
EXPECT_FALSE(contains(es, MobileGL::E_GL_ARB_tessellation_shader));
|
||||
EXPECT_FALSE(contains(vk, MobileGL::E_GL_ARB_tessellation_shader));
|
||||
const MobileGL::MG_Backend::AdvertisedFeatureSupport tessellation{.TessellationShader = true};
|
||||
EXPECT_TRUE(contains(MobileGL::MG_Backend::DirectGLES::BuildAdvertisedExtensions(false, false, false, false,
|
||||
false, false, tessellation),
|
||||
MobileGL::E_GL_ARB_tessellation_shader));
|
||||
EXPECT_TRUE(contains(MobileGL::MG_Backend::DirectVulkan::BuildAdvertisedExtensions(false, false, false, false,
|
||||
false, tessellation),
|
||||
MobileGL::E_GL_ARB_tessellation_shader));
|
||||
}
|
||||
|
||||
// ES 3.2 has tessellation in core; ES 3.1 only through GL_EXT_tessellation_shader. Either way the
|
||||
// patch-size entry point has to have resolved.
|
||||
TEST(TessellationCapabilities, FollowTheVersionOrTheExtension) {
|
||||
const auto funcs = MakeFakeGLESFunctions();
|
||||
auto withPatch = funcs;
|
||||
withPatch.glPatchParameteri = [](GLenum, GLint) {};
|
||||
|
||||
ResetFakeDriver();
|
||||
g_fake.maxVertexSsboBlocks = 0;
|
||||
MobileGL::MG_External::GLESCapabilities es31;
|
||||
ASSERT_TRUE(MobileGL::MG_Util::BackendLoader::FillInGLESCapabilities(es31, withPatch));
|
||||
EXPECT_FALSE(es31.SupportsTessellationShader);
|
||||
|
||||
ResetFakeDriver();
|
||||
g_fake.maxVertexSsboBlocks = 0;
|
||||
g_fake.extensions.emplace_back("GL_EXT_tessellation_shader");
|
||||
MobileGL::MG_External::GLESCapabilities es31Ext;
|
||||
ASSERT_TRUE(MobileGL::MG_Util::BackendLoader::FillInGLESCapabilities(es31Ext, withPatch));
|
||||
EXPECT_TRUE(es31Ext.SupportsTessellationShader);
|
||||
|
||||
ResetFakeDriver();
|
||||
g_fake.maxVertexSsboBlocks = 0;
|
||||
g_fake.glesMinorVersion = 2;
|
||||
MobileGL::MG_External::GLESCapabilities es32NoEntryPoint;
|
||||
ASSERT_TRUE(MobileGL::MG_Util::BackendLoader::FillInGLESCapabilities(es32NoEntryPoint, funcs));
|
||||
EXPECT_FALSE(es32NoEntryPoint.SupportsTessellationShader);
|
||||
|
||||
ResetFakeDriver();
|
||||
g_fake.maxVertexSsboBlocks = 0;
|
||||
g_fake.glesMinorVersion = 2;
|
||||
MobileGL::MG_External::GLESCapabilities es32;
|
||||
ASSERT_TRUE(MobileGL::MG_Util::BackendLoader::FillInGLESCapabilities(es32, withPatch));
|
||||
EXPECT_TRUE(es32.SupportsTessellationShader);
|
||||
}
|
||||
|
||||
// Minecraft 26.3 checks ARB_draw_indirect before it considers the already-advertised
|
||||
// ARB_multi_draw_indirect, then separately requires ARB_base_instance before enabling its terrain
|
||||
// indirect path. Pin both strings and, just as importantly, the non-zero firstInstance gate.
|
||||
|
||||
@@ -1571,6 +1571,57 @@ void main() { mgColor = vec4(float(gl_MaxCullDistances)); }
|
||||
MG_State::pGLContext = Move(previousContext);
|
||||
}
|
||||
|
||||
// GL_EXT_shader_integer_mix (KHR-GL4x.shader_integer_mix.*): a 3.30 shader that requires the
|
||||
// extension must see its macro and must be able to mix integer and boolean vectors under a
|
||||
// boolean selector. Both backends carry the result: SPIR-V lowers the call to OpSelect, which
|
||||
// ESSL 3.10+ and GLSL 4.50 print back as a core boolean mix.
|
||||
TEST(ShaderCompilerSanity, ExtShaderIntegerMixIsUsableAt330) {
|
||||
using namespace MobileGL;
|
||||
|
||||
auto previousContext = MG_State::pGLContext.Take();
|
||||
auto previousBackend = Move(MG_Backend::pActiveBackendObject);
|
||||
MG_State::pGLContext = MakeUnique<MG_State::GLState::GLContext>();
|
||||
MG_Backend::pActiveBackendObject = MakeUnique<DynamicParameterBackend>(MG_Backend::DynamicBackendParameters{});
|
||||
const auto env = MG_Util::ShaderTranspiler::CaptureCompileEnv();
|
||||
|
||||
const auto compile = [&env](GLenum stage, const String& source) {
|
||||
return MG_Util::ShaderTranspiler::ShaderCompiler::CompileShader({
|
||||
.shaderType = stage,
|
||||
.sourceStr = source,
|
||||
.env = env.get(),
|
||||
});
|
||||
};
|
||||
|
||||
const String defineProbe = R"(#version 330
|
||||
#extension GL_EXT_shader_integer_mix: require
|
||||
#if !defined GL_EXT_shader_integer_mix
|
||||
# error GL_EXT_shader_integer_mix is not defined
|
||||
#elif GL_EXT_shader_integer_mix != 1
|
||||
# error GL_EXT_shader_integer_mix is not equal to 1
|
||||
#endif
|
||||
void main(void) { gl_Position = vec4(0); }
|
||||
)";
|
||||
auto define = compile(GL_VERTEX_SHADER, defineProbe);
|
||||
EXPECT_TRUE(define) << (define ? String() : define.error().log);
|
||||
|
||||
const String mixes = R"(#version 330
|
||||
#extension GL_EXT_shader_integer_mix: enable
|
||||
uniform ivec4 a; uniform ivec4 b; uniform uvec4 c; uniform uvec4 d; uniform bvec4 sel;
|
||||
flat out ivec4 i; flat out uvec4 u; flat out ivec4 bo;
|
||||
void main(void) {
|
||||
i = mix(a, b, sel);
|
||||
u = mix(c, d, sel);
|
||||
bo = ivec4(mix(bvec4(a), bvec4(b), sel));
|
||||
gl_Position = vec4(0);
|
||||
}
|
||||
)";
|
||||
auto mixed = compile(GL_VERTEX_SHADER, mixes);
|
||||
EXPECT_TRUE(mixed) << (mixed ? String() : mixed.error().log);
|
||||
|
||||
MG_Backend::pActiveBackendObject = Move(previousBackend);
|
||||
MG_State::pGLContext = Move(previousContext);
|
||||
}
|
||||
|
||||
TEST(GetterSanity, ReportsKhrSubgroupDynamicParameters) {
|
||||
using namespace MobileGL;
|
||||
|
||||
|
||||
@@ -1123,6 +1123,7 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
// Combined with the three entry points below; DirectGLES emulates baseInstance when this
|
||||
// comes out false, so a stub pointer counting as support would silently break the draws.
|
||||
Bool hasBaseInstanceExtension = false;
|
||||
Bool hasTessellationShaderExtension = false;
|
||||
for (GLint i = 0; i < extCount; ++i) {
|
||||
const char* extension = (const char*)glesFuncs.glGetStringi(GL_EXTENSIONS, i);
|
||||
if (extension) {
|
||||
@@ -1180,6 +1181,9 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
if (std::strcmp(extension, "GL_EXT_base_instance") == 0) {
|
||||
hasBaseInstanceExtension = true;
|
||||
}
|
||||
if (std::strcmp(extension, "GL_EXT_tessellation_shader") == 0) {
|
||||
hasTessellationShaderExtension = true;
|
||||
}
|
||||
if (std::strcmp(extension, "GL_EXT_disjoint_timer_query") == 0) {
|
||||
caps.SupportsDisjointTimerQuery = true;
|
||||
}
|
||||
@@ -1281,6 +1285,8 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
glesFuncs.glDrawElementsIndirect != nullptr;
|
||||
caps.SupportsDrawElementsBaseVertex = (esAtLeast32 || hasDrawElementsBaseVertexExtension) &&
|
||||
glesFuncs.glDrawElementsBaseVertex != nullptr;
|
||||
caps.SupportsTessellationShader = (esAtLeast32 || (esAtLeast31 && hasTessellationShaderExtension)) &&
|
||||
glesFuncs.glPatchParameteri != nullptr;
|
||||
caps.SupportsComputeShader = esAtLeast31 && glesFuncs.glDispatchCompute != nullptr &&
|
||||
glesFuncs.glMemoryBarrier != nullptr &&
|
||||
glesFuncs.glCreateShader != nullptr &&
|
||||
@@ -1308,6 +1314,8 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
MGLOG_I(" draw elements base vertex (ES 3.2 core or EXT/OES_draw_elements_base_vertex): %s",
|
||||
caps.SupportsDrawElementsBaseVertex ? "yes" : "no");
|
||||
MGLOG_I(" compute shaders (ES 3.1 core): %s", caps.SupportsComputeShader ? "yes" : "no");
|
||||
MGLOG_I(" tessellation shaders (ES 3.2 core or EXT_tessellation_shader): %s",
|
||||
caps.SupportsTessellationShader ? "yes" : "no");
|
||||
MGLOG_I(" base instance (EXT_base_instance; emulated by attribute offsets when absent): %s",
|
||||
caps.SupportsBaseInstance ? "yes" : "no");
|
||||
MGLOG_I(" clip distances (EXT_clip_cull_distance): %s", caps.SupportsClipDistance ? "yes" : "no");
|
||||
|
||||
@@ -1114,6 +1114,9 @@ namespace MobileGL {
|
||||
Bool SupportsTextureBorderClamp = false;
|
||||
// GL_TEXTURE_CUBE_MAP_ARRAY: ES 3.2 core, or EXT/OES_texture_cube_map_array before it.
|
||||
Bool SupportsTextureCubeMapArray = false;
|
||||
// Tessellation stages: ES 3.2 core, or GL_EXT_tessellation_shader on 3.1, with
|
||||
// glPatchParameteri resolved either way.
|
||||
Bool SupportsTessellationShader = false;
|
||||
// GL_EXT_texture_view / GL_OES_texture_view: two ES texture names sharing one
|
||||
// storage, i.e. the only way DirectGLES can answer glTextureView at all. ES never
|
||||
// made this core - not even in 3.2 - so unlike every other capability here there is
|
||||
|
||||
@@ -259,6 +259,7 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
supportedFeatures.vertexPipelineStoresAndAtomics == VK_TRUE;
|
||||
caps.SupportsFragmentStoresAndAtomics = supportedFeatures.fragmentStoresAndAtomics == VK_TRUE;
|
||||
caps.SupportsGeometryShader = supportedFeatures.geometryShader == VK_TRUE;
|
||||
caps.SupportsTessellationShader = supportedFeatures.tessellationShader == VK_TRUE;
|
||||
caps.SupportsShaderClipDistance = supportedFeatures.shaderClipDistance == VK_TRUE;
|
||||
caps.SupportsShaderCullDistance = supportedFeatures.shaderCullDistance == VK_TRUE;
|
||||
caps.MaxShaderStorageBlockSize = static_cast<SizeT>(p.limits.maxStorageBufferRange);
|
||||
@@ -372,6 +373,7 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
caps.SupportsVertexPipelineStoresAndAtomics = false;
|
||||
caps.SupportsFragmentStoresAndAtomics = false;
|
||||
caps.SupportsGeometryShader = false;
|
||||
caps.SupportsTessellationShader = false;
|
||||
caps.SupportsShaderClipDistance = false;
|
||||
caps.SupportsShaderCullDistance = false;
|
||||
caps.MaxShaderStorageBlockSize = static_cast<SizeT>(properties.limits.maxStorageBufferRange);
|
||||
|
||||
@@ -117,6 +117,9 @@ namespace MobileGL {
|
||||
Bool SupportsVertexPipelineStoresAndAtomics = false;
|
||||
Bool SupportsFragmentStoresAndAtomics = false;
|
||||
Bool SupportsGeometryShader = false;
|
||||
// VkPhysicalDeviceFeatures::tessellationShader, which VulkanRenderer enables wherever
|
||||
// the physical device has it.
|
||||
Bool SupportsTessellationShader = false;
|
||||
// VkPhysicalDeviceFeatures::shaderClipDistance. maxClipDistances is a LIMIT and is
|
||||
// reported whatever the feature says, so the limit alone does not mean a module may
|
||||
// declare ClipDistance - VulkanRenderer enables the feature only where the physical
|
||||
|
||||
Reference in New Issue
Block a user