Uh oh!
There was an error while loading. Please reload this page.
Emulate VK_EXT_host_query_reset so DXVK can create a D3D11 device - #12
Open
abesmon wants to merge 1 commit into
Open
Emulate VK_EXT_host_query_reset so DXVK can create a D3D11 device#12abesmon wants to merge 1 commit into
abesmon wants to merge 1 commit into
Conversation
abesmon
marked this pull request as draft
September 6, 2026 17:37
abesmon
commented
Sep 6, 2026
ContributorAuthor
wait... i found something. Need to research some more stuff |
DXVK's D3D11 path forces this feature on and cannot be talked out of it. D3D11Device::GetDeviceFeatures sets enabled.extHostQueryReset.hostQueryReset = VK_TRUE; inside the >= D3D_FEATURE_LEVEL_9_1 block, and DxvkAdapter::checkFeatureSupport then gates device creation on (supported || !required). So on a driver that does not advertise it, every feature level is refused, not only the high ones -- which is why on Tegra X1 under the NVIDIA proprietary Android driver D3D9 ran while every D3D10/D3D11 title died at device creation with E_INVALIDARG, Unity reporting "d3d11: failed to create device and context (80070057)". This is the only capability that behaves that way. Everything else DXVK asks for in that function, memoryPriority and timelineSemaphore included, is assigned as `enabled.x = supported.x`, so it is required only when it is already present and can never fail the check. Read from the version the device actually runs, DXVK-Sarek v1.11.0, and confirmed on hardware: with the emulation on and nothing else, D3D10 and D3D11 pass in both bitnesses. leegao's bionic-vulkan-wrapper reached the same conclusion independently and is the precedent for the approach. It advertises exactly this extension, under a comment naming DXVK as the reason: // Needed by dxvk exts->EXT_host_query_reset = true; and masks the feature back off in the chain forwarded to the driver, which is what process_pnext_chain does here. It advertises nothing for memory priority. Where this patch differs is the part behind the advertisement. That wrapper implements no vkResetQueryPool, which costs nothing on its targets -- Adreno 6xx and Mali G52 onwards support the feature natively, so the advertisement is a no-op there and the driver's own entry point is used. On a driver that genuinely lacks it there is nothing behind the claim, and DXVK calls the entry point on a hot path: DxvkGpuQueryManager::writeTimestamp and beginSingleQuery reset a query before every timestamp and every query begin. So it is emulated rather than merely claimed. vkResetQueryPool must have taken effect by the time it returns -- it "sets the status of query indices [firstQuery, firstQuery + queryCount - 1] to unavailable" -- so it records vkCmdResetQueryPool into a command buffer, submits it, and waits on a fence. Pool, command buffer and fence are created once at device creation. https://docs.vulkan.org/refpages/latest/refpages/source/vkResetQueryPool.html The emulation inherits the entry point's own valid usage, which does most of the work: the application must already have completed submitted commands referring to the range, and must not have that range in use from another thread. So the reset never races the application's use of those queries. What it can race is unrelated work on the queue it submits to, and that is the whole design problem. Sharing the application's queue couples the reset to whatever is already queued on it: a legal application submit can wait on a host event the application only signals after its reset returns, and the reset then waits for work that is waiting for the reset. A probe arms a vkCmdWaitEvents on the application queue and releases the event from a watchdog thread after one second, so this shows up as latency rather than a hang. On Tegra a shared-queue implementation waited 1001 ms in five runs out of five -- the full watchdog, every time. So the emulation asks vkCreateDevice for one extra queue in a family the application already requested, and submits there. The application never learns about it: wrapper_create_device_queue builds wrapper_queue objects from the application's own VkDeviceCreateInfo, not from the one forwarded to the driver. Same probe, same device: 0.2 ms instead of 1001 ms. If the family has no spare queue the emulation falls back to sharing the application's first graphics/compute queue and restores the serialisation that needs, because a VkQueue is externally synchronised and the application cannot synchronise against a submit it does not know about. Refusing to create the device there would turn a slow device into no device at all. wrapper_query_reset_owns_queue is false whenever the queue is private, so the private path pays nothing for the fallback. vkDeviceWaitIdle is serialised against the internal queue for the same reason: its host synchronisation requirement covers "all VkQueue objects created from device", and one of them is invisible to the application. https://docs.vulkan.org/refpages/latest/refpages/source/vkDeviceWaitIdle.html Only the core entry point is defined. The generated table lists vkResetQueryPool and vkResetQueryPoolEXT separately but both resolve to one dispatch slot, and defining the alias as well trips the "disp[disp_index] == NULL" assert in vk_device_dispatch_table_from_entrypoints and kills device creation. That mistake was made and caught on the device. Gated like the native BCn preference and the AHB ownership release: on the driver, with WRAPPER_EMULATE_HOST_QUERY_RESET as a tri-state override, and never applied over native support. The emulation is not free -- every host reset is a command buffer and a fence wait, about 80-120 us on this hardware -- so the kill switch exists for a client that does not need it.
abesmon
commented
Sep 6, 2026
ContributorAuthor
i've retested everything, and found that part of fix was unnecessary, so i removed it. Now only VK_EXT_host_query_reset emulation is here. Also found, that leegao already made similar stuff |
abesmon
marked this pull request as ready for review
September 6, 2026 18:20
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Emulate VK_EXT_host_query_reset so DXVK can create a D3D11 device
The problem
DXVK's D3D11 path forces
hostQueryReseton and cannot be talked out of it.D3D11Device::GetDeviceFeatures:and DxvkAdapter::checkFeatureSupport gates device creation on
(m_deviceFeatures.… || !required.…). So a driver that does not advertise the
feature gets no D3D11 device at any feature level, not just the high ones.
On Tegra X1 under the NVIDIA proprietary Android driver that is why D3D9 ran
while every D3D10 and D3D11 title died at device creation. From a Unity title:
80070057 is E_INVALIDARG. DXGI works and the adapter is found; only device
creation is refused, at 11_1, 11_0, 10_1 and 10_0 alike.
This is the only capability in that function that behaves this way.
Everything else DXVK asks for there — memoryPriority and timelineSemaphore
included — is assigned as enabled.x = supported.x, so it is required only when
already present and can never fail the check. Read at the version the device
actually runs, DXVK-Sarek v1.11.0.
Prior art
leegao/bionic-vulkan-wrapper reached the same conclusion independently and is
the precedent for the approach. It advertises exactly this extension, naming
DXVK as the reason:
and masks the feature back off in the chain forwarded to the driver, which is
what process_pnext_chain does here. It advertises nothing for memory priority.
Where this patch differs is what sits behind the advertisement. That wrapper
implements no vkResetQueryPool. On its targets that costs nothing — Adreno 6xx
and Mali G52 onwards support the feature natively, so the advertisement is a
no-op and the driver's own entry point is used. On a driver that genuinely lacks
it there is nothing behind the claim, and DXVK calls the entry point on a hot
path: DxvkGpuQueryManager::writeTimestamp and beginSingleQuery reset a query
before every timestamp and every query begin.
So it is emulated rather than merely claimed.
Gating
Driver-gated, the same way as the native-BCn preference and the AHB ownership
release already in this tree:
WRAPPER_EMULATE_HOST_QUERY_RESET is tri-state: unset follows the driver
default, true opts another driver in, false is a kill switch