mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-10 21:28:32 +09:00
[Feat] (DirectVulkan, MG_Util): honour a glVertexAttribDivisor other than 1
Vulkan's VK_VERTEX_INPUT_RATE_INSTANCE advances an attribute once per instance and has no way to say anything else, so every non-zero divisor collapsed to 1: an attribute the application asked to change every three instances changed every one, and KHR-GL40.draw_indirect.basic-drawArrays-instancing and its elements sibling drew the wrong colours from instance one onward. VK_EXT_vertex_attribute_divisor is exactly this state, so it is enabled when the device has it and the per-binding divisors ride into the pipeline through VkPipelineVertexInputDivisorStateCreateInfoEXT. Only divisors other than 1 are listed - 1 is what the plain input rate already means - and they join the layout hash, so two layouts that differ only in a divisor no longer share a pipeline. POST reports the feature either way, because without it the failure is silent and looks like a shader bug: the attribute is fetched, just from the wrong instance. The GLES side gains the two checks this session's other work made load-bearing for the same reason - glPatchParameteri (without it GL_PATCH_VERTICES stays at the driver's 3 and a patch draw of any other size renders nothing) and the transform feedback object entry points (without them a second object cannot open a capture while the first is paused). KHR-GL40.draw_indirect on Magma: 70/70 but for the arbitrary primitive-restart index, which Vulkan cannot express at all.
This commit is contained in:
@@ -298,6 +298,25 @@ namespace MobileGL::MG_Util::SelfTest {
|
||||
"not supported; no impact: the native indirect path deliberately does not "
|
||||
"rely on it (shader-side emulation handles baseInstance semantics)");
|
||||
}
|
||||
if (glesFuncs.glPatchParameteri != nullptr) {
|
||||
builder.Pass("Tessellation patch parameters",
|
||||
"glPatchParameteri present (GL_PATCH_VERTICES reaches the driver)");
|
||||
} else {
|
||||
builder.Warn("Tessellation patch parameters",
|
||||
"glPatchParameteri missing (pre-ES 3.2 without GL_EXT_tessellation_shader); "
|
||||
"GL_PATCH_VERTICES stays at the driver default of 3 and a patch draw of any "
|
||||
"other size renders nothing");
|
||||
}
|
||||
if (glesFuncs.glGenTransformFeedbacks != nullptr && glesFuncs.glBindTransformFeedback != nullptr &&
|
||||
glesFuncs.glPauseTransformFeedback != nullptr && glesFuncs.glResumeTransformFeedback != nullptr) {
|
||||
builder.Pass("Transform feedback objects",
|
||||
"supported (each GL transform feedback object gets one of the driver's, so "
|
||||
"several can hold a paused capture at once)");
|
||||
} else {
|
||||
builder.Warn("Transform feedback objects",
|
||||
"entry points missing; every GL transform feedback object shares the driver's "
|
||||
"default one, so a second object cannot open a capture while the first is paused");
|
||||
}
|
||||
if (caps.SupportsNorm16Texture) {
|
||||
builder.Pass("GL_EXT_texture_norm16", "supported");
|
||||
} else {
|
||||
@@ -1412,6 +1431,27 @@ namespace MobileGL::MG_Util::SelfTest {
|
||||
"hard-fails at draw");
|
||||
}
|
||||
|
||||
Bool vertexAttributeInstanceRateDivisor = false;
|
||||
if (vkGetPhysicalDeviceFeatures2Fn != nullptr &&
|
||||
HasVkExtension(deviceExtensions, VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME)) {
|
||||
VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT divisorFeatures{};
|
||||
divisorFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT;
|
||||
VkPhysicalDeviceFeatures2 features2{};
|
||||
features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
|
||||
features2.pNext = &divisorFeatures;
|
||||
vkGetPhysicalDeviceFeatures2Fn(physicalDevice, &features2);
|
||||
vertexAttributeInstanceRateDivisor = divisorFeatures.vertexAttributeInstanceRateDivisor == VK_TRUE;
|
||||
}
|
||||
if (vertexAttributeInstanceRateDivisor) {
|
||||
builder.Pass("vertexAttributeInstanceRateDivisor",
|
||||
"supported (glVertexAttribDivisor advances an attribute every N instances)");
|
||||
} else {
|
||||
builder.Warn("vertexAttributeInstanceRateDivisor",
|
||||
"unsupported; Vulkan's instance input rate can only advance once per instance, so "
|
||||
"every non-zero glVertexAttribDivisor behaves as 1 and instanced attributes meant to "
|
||||
"change every N instances change every one");
|
||||
}
|
||||
|
||||
if (vkGetPhysicalDeviceProperties2Fn != nullptr && properties.apiVersion >= VK_API_VERSION_1_1) {
|
||||
VkPhysicalDeviceSubgroupProperties subgroupProperties{};
|
||||
subgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
|
||||
|
||||
Reference in New Issue
Block a user