Direct3D implicit synchronization implementation method based on double-stage semaphore synchronization agent

CN122903099APending Publication Date: 2026-10-13北京麟卓信息科技有限公司
View PDF 0 Cites 0 Cited by

Patent Information

Application Number
CN202611382839.5
Authority / Receiving Office
CN · China
Patent Type
Applications(China)
Current Assignee / Owner
Filing Date
2026-09-08
Publication Date
2026-10-13

AI Technical Summary

Technical Problem

[0004]在不支持VK_KHR_present_wait扩展的老旧GPU上,DXVK将面临以下技术问题:一是隐式同步语义映射失效,DXVK无法将D3D的隐式同步Present调用转换为Vulkan的精确同步操作,导致呈现操作与后续的图像获取、资源修改操作之间缺乏可靠的同步屏障,易引发图像数据竞争,如渲染与呈现同时访问同一图像资源;二是交换链图像重用风险,交换链作为D3D与Vulkan共享的图像缓冲池,其图像的生命周期需严格遵循从获取、渲染、呈现、释放到重用的流程,缺乏呈现完成事件时,DXVK无法判断图像是否已被显示引擎消耗,过早重用会导致画面撕裂、花屏,过晚重用则造成显存资源浪费;三是多线程并发同步混乱,D3D应用普遍采用多线程架构,多个线程可能同时触发图像获取、命令提交、Present调用等操作,缺乏统一的呈现完成同步点时,易出现命令流执行顺序错乱、图像状态跟踪不一致等竞态条件;四是D3D高级同步功能缺失,D3D的Present1调用支持自定义呈现参数、垂直同步控制、呈现时序查询等高级功能,这些功能均依赖呈现完成时机的精确感知,无VK_KHR_present_wait时无法实现完整语义映射;五是多线程异常处理缺失,现有方案未针对线程崩溃导致同步资源泄漏、命令提交失败引发依赖链断裂、信号量等待超时导致死锁等多线程异常场景设计容错机制,易造成DXVK崩溃或应用卡死;六是序列化屏障效率低下,现有多线程同步依赖全局锁或重量级信号量,导致命令流提交吞吐量下降,尤其在高帧率场景下,锁竞争开销占比明显提升

Benefits of technology

[0023]本发明在D3D应用在帧渲染循环前初始化创建逻辑渲染设备,DXVK拦截该创建设备调用并创建Vulkan实例与逻辑设备,查询GPU对VK_KHR_present_wait扩展的支持情况,当GPU不支持该扩展时,DXVK创建Vulkan信号量池与内核事件FD池,生成二者一一对应的第一映射表并初始化原子计数器,向DRM子系统发送代理初始化请求以初始化包含多类字段的呈现事件代理表,FB-ID与CRTC-ID在交换链图像绑定时填入;D3D应用创建D3D交换链,DXVK拦截交换链创建调用,创建Vulkan交换链并计算呈现完成超时阈值,为每张交换链图像分配信号量与事件FD并完成内核绑定,初始化图像原子状态寄存器,构建包含多类数组、指针与变量的交换链全局同步上下文;D3D应用发起命令列表创建或重置请求、执行命令列表渲染命令记录,DXVK依次完成Vulkan命令缓冲创建、依赖链节点分配、呈现同步依赖绑定、D3D指令向Vulkan指令的转换写入、资源屏障绑定,针对渲染目标写入追加信号量触发操作,借助原子操作标记图像渲染状态,完成命令缓冲、依赖节点、信号量与图像的关联存储;D3D应用依次发起命令队列提交命令列表、触发图像呈现,DXVK拦截对应调用,构建依赖链实现命令流序列化并提交Vulkan命令缓冲,与已初始化完成的双级信号量同步代理建立运行时关联,完成呈现参数解析、垂直同步及多交换链处理,组装并提交Vulkan呈现请求至呈现队列,提交后执行CPU侧原子状态更新。

✦ Generated by Eureka AI based on patent content.

Smart Images

  • Figure CN122903099A_ABST
    Figure CN122903099A_ABST
Patent Text Reader

Abstract

The application discloses a Direct3D implicit synchronization implementation method based on a two-stage semaphore synchronization agent, and the method comprises the following steps: after a D3D application creates a logical device, a DXVK creates a Vulkan instance, a Vulkan semaphore pool and a kernel event FD pool are created when a GPU does not support a VK_KHR_present_wait extension, and a two-stage semaphore synchronization agent is triggered to initialize; when an exchange chain is created, the DXVK creates a Vulkan exchange chain, allocates resources for an exchange chain image, and adds the exchange chain image to an epoll polling; when a command list is created and submitted, the DXVK adapts a D3D instruction and a resource barrier to generate a local synchronization condition, allocates a dependent chain node of an associated synchronization agent, accesses a device instance dependent chain, and then submits a command buffer; when an application triggers image presentation, the DXVK constructs a Vulkan presentation and submits a task, a synchronization agent monitors a scan-out completion event, updates an exchange chain image state, and implicit synchronization is realized.
Need to check novelty before this filing date? Find Prior Art

Description

Technical Field

[0001] This invention belongs to the field of computer software development technology, specifically relating to a Direct3D implicit synchronization implementation method based on a two-level semaphore synchronization proxy. Background Technology

[0002] As an open-source API translation layer, DXVK's core function is to translate D3D9-11 API calls into Vulkan API instructions, enabling D3D-dependent applications to run on Vulkan-enabled hardware and operating systems such as Linux. The VK_KHR_present_wait extension is a key component in the Vulkan specification for synchronizing presentation operations. Its core function is to allow applications to explicitly wait on the CPU side for the completion of presentation operations triggered by `vkQueuePresentKHR`, where the presentation operation is the image display and output process triggered by the `vkQueuePresentKHR` call. This extension provides host-side presentation completion notification capabilities, allowing DXVK to simulate some implicit D3D synchronization behaviors and narrow the differences between the synchronization models of D3D and Vulkan.

[0003] D3D uses an implicit synchronization model, where its Present calls automatically wait for rendering and presentation operations to complete after execution, ensuring that subsequent operations such as image reuse and state queries are based on the correct synchronization state. This implicit waiting behavior is disabled if the DXGI_PRESENT_DO_NOT_WAIT flag is set. Vulkan, on the other hand, uses an explicit synchronization model. The vkQueuePresentKHR call only submits presentation requests asynchronously and does not output Vulkan semaphore objects that can be waited on by the GPU queue. The VK_KHR_present_wait extension provides CPU host-side waiting capabilities, allowing applications to capture presentation completion events on the CPU. This extension does not provide semaphore objects that the GPU can wait on.

[0004] On older GPUs that do not support the VK_KHR_present_wait extension, DXVK will face the following technical problems: First, implicit synchronization semantic mapping fails. DXVK cannot convert D3D's implicit synchronization Present call into Vulkan's precise synchronization operation, resulting in a lack of reliable synchronization barriers between the rendering operation and subsequent image acquisition and resource modification operations. This can easily lead to image data contention, such as rendering and rendering accessing the same image resource simultaneously. Second, there is a risk of image reuse in the swap chain. As an image buffer pool shared by D3D and Vulkan, the swap chain's image lifecycle must strictly follow the process from acquisition, rendering, rendering, release to reuse. Without a rendering completion event, DXVK cannot determine whether the image has been consumed by the display engine. Premature reuse can lead to screen tearing and glitches, while late reuse can waste video memory resources. Third, there is chaos in multi-threaded concurrent synchronization. D3D applications generally adopt a multi-threaded architecture, and multiple threads may trigger concurrently. When operations such as image acquisition, command submission, and Present call lack a unified synchronization point for presentation completion, race conditions such as disordered command flow execution order and inconsistent image state tracking can easily occur. Fourth, advanced D3D synchronization functions are missing. D3D's Present1 call supports advanced functions such as custom presentation parameters, vertical synchronization control, and presentation timing query. These functions all rely on precise perception of the presentation completion timing. Without VK_KHR_present_wait, complete semantic mapping cannot be achieved. Fifth, multi-threaded exception handling is lacking. Existing solutions do not design fault tolerance mechanisms for multi-threaded exception scenarios such as thread crashes leading to synchronization resource leaks, command submission failures causing dependency chain breaks, and semaphore wait timeouts leading to deadlocks. This can easily cause DXVK crashes or application freezes. Sixth, serialization barriers are inefficient. Existing multi-threaded synchronization relies on global locks or heavyweight semaphores, resulting in a decrease in command flow submission throughput. Especially in high frame rate scenarios, the proportion of lock contention overhead increases significantly.

[0005] However, existing improvement solutions have significant drawbacks. Using `vkWaitQueueIdle` to wait for the entire GPU queue to become idle causes the CPU to be blocked on irrelevant computations and rendering operations, leading to increased performance degradation. Estimating rendering completion time through CPU busy waiting is prone to synchronization errors due to hardware differences and frame rate fluctuations, increasing screen tearing. Increasing the number of images in the swap chain can reduce the probability of conflicts, but it doubles the memory usage and cannot solve synchronization problems in dynamic refresh rate scenarios. Multi-threaded synchronization relies on global locks, causing performance bottlenecks to become apparent in high-concurrency scenarios. Therefore, there is an urgent need for an innovative solution that does not rely on intelligent algorithms but is based on underlying hardware and operating system mechanisms to achieve efficient synchronous conversion from D3D to Vulkan on GPUs that do not support `VK_KHR_present_wait`, while simultaneously solving the efficiency issues of exception handling and serialization barriers. Summary of the Invention

[0006] In view of this, the present invention provides a Direct3D implicit synchronization implementation method based on a two-level semaphore synchronization proxy. By intercepting the calls of each stage of the D3D rendering loop in the DXVK translation layer and establishing a two-level semaphore synchronization proxy, the timing synchronization control of D3D image rendering and Vulkan rendering is realized on GPUs that do not support VK_KHR_present_wait.

[0007] The Direct3D implicit synchronization implementation method based on a two-level semaphore synchronization proxy provided by this invention specifically includes the following steps:

[0008] During D3D application initialization, D3D device instances and D3D logical devices are created. DXVK correspondingly creates Vulkan instances and Vulkan logical devices. If the GPU supports the VK_KHR_present_wait extension, the native wait path is used for execution; otherwise, a Vulkan semaphore pool and a kernel event FD pool are created. Event FDs and Vulkan semaphores are mapped one-to-one to form the first mapping table. DXVK sends an initialization request carrying the first mapping table to the DRM subsystem, triggering a two-level semaphore synchronization agent to complete kernel-mode and user-mode initialization.

[0009] The D3D application creates a D3D swap chain, and the corresponding DXVK application creates a Vulkan swap chain. The rendering completion timeout threshold is set according to the display refresh rate. Semaphores are allocated from the Vulkan semaphore pool and event FDs are allocated from the kernel event FD pool for the swap chain image. The binding relationship between semaphore identifiers, event FD identifiers, framebuffer object identifiers and screen identifiers is registered with the kernel. The event FDs are added to the epoll event polling instance. The status register of the swap chain image is set to idle.

[0010] The D3D application creates a command list, and DXVK creates a corresponding Vulkan command buffer. The D3D instructions in the command list are converted into Vulkan instructions and written into the Vulkan command buffer. The D3D resource barriers in the command list are converted into Vulkan memory barriers, forming GPU local synchronization conditions.

[0011] When a D3D application submits a command list, DXVK allocates a dependency chain node for the command list. This dependency chain node describes the rendering synchronization dependency corresponding to this submission. The generated GPU local synchronization conditions are added to the rendering synchronization dependency, and the rendering completion semaphore, image index, synchronization resource identifier, and waiting conditions are recorded. This dependency chain node establishes a runtime association with the two-level semaphore synchronization agent. This dependency chain node is then connected to the dependency chain of its respective D3D device instance, and the Vulkan command buffer is submitted.

[0012] When a D3D application triggers image rendering, DXVK builds the Vulkan rendering configuration and submits a rendering request to add the image output task to the rendering queue. The kernel's two-level semaphore synchronization agent detects that the display hardware scan output is complete, triggers an event, and updates the corresponding exchange chain image state.

[0013] Furthermore, it also includes: configuring a mutex lock on the dependency chain corresponding to the D3D device instance; acquiring the mutex lock when performing dependency chain node access, deletion, or traversal operations on the dependency chain; releasing the mutex lock after the operation is completed; and modifying the predecessor and successor pointers of the dependency chain when accessing a dependency chain node.

[0014] Furthermore, adaptation state recycling processing is performed on the swap chain images for different swap effect types: For DXVK swap chain images in bit block copy mode, the swap chain image is marked as idle and returned to the swap chain image pool after rendering is completed, without waiting for application release; for DXVK swap chain images in flip mode, they are not processed immediately after rendering is completed, but are marked as idle and returned to the swap chain image pool when the operation of obtaining the next frame image is performed; for DXVK swap chain images in flip-drop mode, GPU-side read and write access synchronization is completed by binding resource barrier synchronization objects, and the swap chain image is marked as idle and returned to the swap chain image pool after the kernel detects that the display hardware scan output is complete.

[0015] Furthermore, when the D3D application triggers image rendering, DXVK parses the rendering configuration parameters carried in this rendering call: When configured for no-wait mode, the event polling timeout is set to zero, and the system returns success directly without blocking the rendering completion wait, and marks the corresponding swap chain image as skipping the rendering completion wait logic; when configured for reset mode, the DRM subsystem's custom interface is called to reset the corresponding entry in the kernel mapping table of the two-level semaphore synchronization agent, rebind the rendering completion semaphore and event FD, and reset the swap chain image state to pending rendering; when configured for stereoscopic rendering mode, independent semaphore identifiers and event FD identifiers are assigned to the left and right eye images respectively and bound to the same display controller, and the overall rendering is considered complete only when all rendering completion events for the left and right eyes are triggered; when configured for delayed rendering mode, the current rendering task is added to the user-mode delayed queue, and all tasks in the queue are submitted in batches when the next rendering call is triggered.

[0016] Furthermore, when the application enables vertical synchronization, it sends the configuration to the dual-level semaphore synchronization agent. After receiving the image output task, the kernel only triggers the rendering completion event after the vertical blanking signal of the display arrives. When the application disables vertical synchronization, it notifies the kernel to trigger the rendering completion event immediately after the image scan output is completed. When the application enables adaptive vertical synchronization, it sends an adaptive mode flag to the kernel. The kernel counts the real-time frame rate and dynamically adjusts the event triggering timing: when the frame rate is higher than the display refresh rate, vertical synchronization is enabled, and the event is triggered after the vertical blanking signal arrives; when the frame rate is lower than the display refresh rate, vertical synchronization is disabled, and the event is triggered immediately after the image scan output is completed.

[0017] Furthermore, if there are multiple exchange chains under the current D3D device instance, multi-exchange chain synchronization processing is performed: the current image index and rendering completion semaphore of all exchange chains are read, a global rendering dependency relationship is constructed, and the rendering operation of the main exchange chain waits for the rendering completion signals of all sub-exchange chains; the custom interface of the DRM subsystem is called to register the multi-exchange chain binding relationship with the kernel, and the kernel will only trigger the rendering completion event corresponding to all exchange chains synchronously after all the bound exchange chains have completed image scanning and output.

[0018] Furthermore, after the display engine completes image scanning and output, the display controller driver generates a hardware interrupt. The interrupt handler reads the current frame buffer identifier, the display controller identifier, and the hardware scan completion timestamp, queries the presentation event proxy table, and obtains the corresponding semaphore identifier, event FD identifier, and semaphore status. If the semaphore has not yet been triggered, data is written to the corresponding event FD after the vertical synchronization constraint is met, thus waking up a user-mode readable event. When the application enables vertical synchronization, it needs to wait for the display's vertical blanking signal to arrive before executing the event writing, so that the presentation event is aligned with the display refresh cycle. Then, the semaphore status in the presentation event proxy table is updated to "triggered" and the frame completion timestamp is recorded.

[0019] Furthermore, it also includes: the user-space proxy layer of the two-level semaphore synchronization proxy configures the epoll event polling instance to edge-triggered mode during the exchange chain initialization phase, and listens for readable events of event FD with a preset timeout threshold after submitting a rendering request; after capturing a readable event, it sets the rendering completion semaphore of the corresponding image to the triggered state; when a timeout occurs, it marks the image as abnormal and enters the exception handling process; when a hardware exception occurs, it logs the exception and resets the semaphore and event FD after the GPU device is idle; the user-space proxy layer queries the kernel mapping table through a custom kernel call, and performs a forced trigger operation when the kernel marks the semaphore as triggered but the user-space semaphore is not effective.

[0020] Furthermore, the dependency chain node is connected to the dependency chain of its D3D device instance using an atomic lock-free connection method: each submitting thread reads the current tail node of the dependency chain; the preceding pointer of the dependency chain node to be connected is set to the tail node, and then an atomic comparison and swap operation is used to try to update the tail pointer of the dependency chain to the dependency chain node to be connected, thus completing the atomic connection of the dependency chain node; when multi-threaded contention causes the atomic comparison and swap operation to fail, the thread rereads the tail node information of the dependency chain and retryes. If the retry still fails after a set number of times, a spin wait is executed.

[0021] Furthermore, DXVK assembles Vulkan rendering configuration information as follows: it specifies the target Vulkan swap chain and the index of the image to be rendered, sets the waiting semaphore for the rendering operation to the rendering completion semaphore of the current frame, so that the rendering operation is executed after the rendering command is completed; it maps D3D swap effects to Vulkan swap chain rendering modes and retains the internal swap effect type flags; and it provides rendering completion notifications at the hardware scan output level through a two-level semaphore synchronization agent.

[0022] Beneficial effects:

[0023] This invention initializes and creates a logical rendering device before the frame rendering loop in a D3D application. DXVK intercepts this device creation call and creates a Vulkan instance and logical device. It queries the GPU's support for the VK_KHR_present_wait extension. If the GPU does not support this extension, DXVK creates a Vulkan semaphore pool and a kernel event FD pool, generates a one-to-one mapping table between them, initializes atomic counters, and sends a proxy initialization request to the DRM subsystem to initialize a presentation event proxy table containing multiple fields. FB-ID and CRTC-ID are filled in during swap chain image binding. The D3D application creates a D3D swap chain. DXVK intercepts the swap chain creation call, creates a Vulkan swap chain, calculates the rendering completion timeout threshold, allocates semaphores and event FDs to each swap chain image and completes kernel binding, initializes the image atomic state register, and constructs a structure containing multiple arrays, pointers, and variables. The exchange chain of quantities is used for global synchronization context; the D3D application initiates a command list creation or reset request, executes the command list rendering command record, and DXVK sequentially completes the creation of Vulkan command buffer, dependency chain node allocation, rendering synchronization dependency binding, D3D instruction to Vulkan instruction conversion and writing, resource barrier binding, writes appended semaphore trigger operations for rendering target, marks image rendering state with atomic operations, and completes the association storage of command buffer, dependency nodes, semaphores and image; the D3D application sequentially initiates command queue submission of command list and triggers image rendering, DXVK intercepts the corresponding call, builds dependency chain to realize command stream serialization and submits to Vulkan command buffer, establishes runtime association with the initialized two-level semaphore synchronization agent, completes rendering parameter parsing, vertical synchronization and multi-exchange chain processing, assembles and submits Vulkan rendering request to rendering queue, and performs CPU-side atomic state update after submission. Attached Figure Description

[0024] Figure 1 This is a flowchart illustrating the Direct3D implicit synchronization implementation method based on a two-level semaphore synchronization proxy provided by the present invention. Detailed Implementation

[0025] The present invention will be described in detail below with reference to the accompanying drawings and embodiments.

[0026] The Direct3D implicit synchronization implementation method based on a two-level semaphore synchronization proxy provided by this invention has the following core idea: Before the frame rendering loop, the D3D application initializes and creates a logical rendering device. DXVK intercepts this device creation call and creates a Vulkan instance and a logical device. It queries the GPU's support for the VK_KHR_present_wait extension. If the GPU does not support this extension, DXVK creates a Vulkan semaphore pool and a kernel event FD pool, generates a one-to-one mapping table between the two, initializes atomic counters, and sends a proxy initialization request to the DRM subsystem to initialize a presentation event proxy table containing multiple fields. FB-ID and CRTC-ID are filled in during swap chain image binding. The D3D application creates a D3D swap chain. DXVK intercepts the swap chain creation call, creates a Vulkan swap chain, calculates the presentation completion timeout threshold, allocates semaphores and event FDs to each swap chain image, completes kernel binding, and initializes image atoms. The state register constructs a global synchronization context containing various arrays, pointers, and variables via a swap chain. The D3D application initiates a command list creation or reset request and executes the command list rendering command record. DXVK sequentially completes Vulkan command buffer creation, dependency chain node allocation, rendering synchronization dependency binding, D3D instruction to Vulkan instruction conversion and writing, resource barrier binding, and appends semaphore trigger operations for the rendering target. Atomic operations are used to mark the image rendering state, completing the associated storage of the command buffer, dependency nodes, semaphores, and image. The D3D application sequentially initiates command queue submission of the command list and triggers image rendering. DXVK intercepts the corresponding calls, constructs a dependency chain to serialize the command stream and submits it to the Vulkan command buffer, establishes a runtime association with the initialized two-level semaphore synchronization agent, completes rendering parameter parsing, vertical synchronization, and multi-swap chain processing, assembles and submits the Vulkan rendering request to the rendering queue, and performs CPU-side atomic state updates after submission.

[0027] The Direct3D implicit synchronization implementation method based on a two-level semaphore synchronization proxy provided by this invention has the following processing flow: Figure 1 As shown, the specific steps include:

[0028] Step 1: During D3D application initialization, before the frame rendering loop, a D3D logical rendering device is created, passing in device creation parameters including feature level and debug flags. DXVK intercepts the D3D device creation call, obtains and parses the device creation parameters, creates a Vulkan instance and a Vulkan logical device, and queries the Vulkan feature set supported by the GPU. If the VK_KHR_present_wait extension is not supported, proceed to Step 2; otherwise, execute the process as before to end this process.

[0029] Among them, the Feature-Level is a predefined set of GPU functions. When creating a device, the application limits the set of D3D capabilities provided by the device through the Feature-Level. If the hardware does not meet the requirements of the Feature-Level, the device creation will fail or be downgraded to a lower level. Debug flags such as D3D11_CREATE_DEVICE_DEBUG are used to enable the D3D debug layer. When enabled, it allows parameter validation of D3D interface calls and output of debug warning messages.

[0030] Among them, Vulkan instance VkInstance is a process-level global environment object of Vulkan, used to enumerate GPU hardware; Vulkan logical device VkDevice is created by Vulkan instance based on enumerated Vulkan physical device, and is the underlying handle of DXVK used to create GPU resources such as semaphores, command buffers, and swap chains; Vulkan physical device represents the actual GPU hardware and is only used for hardware capability query.

[0031] Step 2: Create a software-level Vulkan semaphore pool to store pre-allocated Vulkan binary semaphores, assigning a unique semaphore ID to each Vulkan binary semaphore; create a software-level kernel event FD pool to store pre-allocated event FDs, assigning a unique FD-ID to each event FD; each event FD corresponds one-to-one with a Vulkan binary semaphore, forming a first mapping table containing semaphore ID, FD-ID, and Vulkan device handle; initialize atomic counters for semaphore IDs and FD-IDs, implemented based on CPU atomic instructions, used to allocate new synchronization resource IDs;

[0032] DXVK sends a proxy initialization request carrying the first mapping table to the DRM subsystem, performs kernel-mode initialization of the two-level semaphore synchronization proxy, and triggers the DRM subsystem to create a presentation event proxy table as a kernel-mode data structure. This presentation event proxy table contains fields such as semaphore ID, FD-ID, FB-ID, CRTC-ID, semaphore status, and timeout. FB-ID and CRTC-ID are filled in when binding the swap chain image.

[0033] DXVK creates an epoll event polling instance, sets the event triggering type to edge-triggered mode, establishes a unified semaphore state bitmap between kernel and user space, registers a custom DRM notification call when the Vulkan semaphore is reset, and ensures that the kernel side presents a synchronously updated event proxy table when the semaphore is reset, thereby completing the user space initialization of the two-level semaphore synchronization proxy.

[0034] The semaphore states include untriggered and triggered. FB-ID is a unique identifier assigned by DRM to the framebuffer object. The framebuffer stores the pixel image data to be scanned and output to the display. The swap chain image is wrapped as a drm_framebuffer at the DRM layer, possessing a corresponding FB-ID. The FB-ID is used to mark the framebuffer to be displayed corresponding to this page flip operation. After the kernel completes the page flip scan output, it can locate the corresponding entry for this display through the FB-ID. CRTC-ID is a unique ID assigned by the kernel to each display controller's CRTC hardware instance. The CRTC-ID records the display controller that performed the page flip in this rendering operation. In multi-monitor scenarios, different screens correspond to different CRTC-IDs. When a kernel vertical interrupt arrives, it uses the CRTC-ID index to find the corresponding proxy entry, triggering the event FD and waking up the upper-layer semaphore.

[0035] The Vulkan semaphore pool is managed using a free list, and list operations are performed using atomic compare-and-swap (CAS) to achieve lock-free access. The first mapping table is stored using an array.

[0036] Step 3: The D3D application creates a D3D swap chain by passing in swap chain creation parameters containing image resolution, format, buffer size, rendering mode, and swap effects; DXVK intercepts the D3D swap chain creation call, obtains and parses the swap chain creation parameters, creates a Vulkan swap chain, obtains the display refresh rate, and sets the rendering completion timeout threshold to a multiple of the single frame period.

[0037] The process iterates through each swap chain image, allocating semaphores from the Vulkan semaphore pool and event FDs from the kernel event FD pool in sequence to obtain valid event FDs. It records the unique identifiers corresponding to both and registers the binding relationships between semaphore IDs, FD-IDs, FB-IDs, and CRTC-IDs with the kernel. After completing the event FD allocation for the swap chain image, it adds the event FD to the epoll event polling instance for event monitoring. It initializes an atomic state register for each swap chain image, marking the image's lifecycle state, with the initial state set to idle.

[0038] DXVK constructs a global synchronization context for the exchange chain and maintains atomic variables that record the index of the currently rendered image. It uses arrays to uniformly store the semaphores and corresponding identifiers, event FDs and corresponding identifiers, and image atomic state registers for all exchange chain images. It sets the head pointer of the lock-free dependency chain to point to the command flow dependency node to be executed, uses atomic variables to count the total number of renderings for upper-layer state queries, and uses a circular queue of atomic access to store the rendering time sequence history data.

[0039] Furthermore, adaptation is implemented for different swap effect types: for images with a bit-block copy swap effect, the image automatically switches back to an idle state after rendering without waiting for the application to actively release it; for images with a flip swap effect, the image state is not reset immediately after rendering, but is reset when the next frame is captured to avoid image data being accidentally overwritten; for images with a flip-discard swap effect, a resource barrier synchronization object is additionally bound, and the image is released immediately after rendering to reduce video memory overhead.

[0040] Step 4: The D3D application initiates a command list creation request. DXVK intercepts the corresponding call, completes the creation of the Vulkan command buffer, and assigns dependency chain nodes to each command list. Each node stores pointers to preceding and following dependency nodes, a preceding rendering completion semaphore flag, a command buffer handle, and an associated image index, as well as atomic state flags used to mark incomplete, ready, executing, and completed states. DXVK completes the binding of command lists and rendering synchronization dependencies.

[0041] The D3D application executes a list of commands to record rendering commands. DXVK intercepts these calls, parses resource access, pipeline state configuration, and other operations in the command stream, and converts D3D instructions into corresponding Vulkan instructions and writes them into the Vulkan command buffer. DXVK binds the D3D resource barrier to the rendering synchronization.

[0042] If a render target write operation exists in the command list, DXVK appends a semaphore trigger operation to the end of the command buffer, selects the render completion semaphore of the corresponding image as the object to be triggered, sets the corresponding pipeline stage wait condition, and ensures that the semaphore is set to the pending trigger state after the render command is executed; it reads the render status bit of the corresponding image in the image status array using atomic operations. If the image is not in the render state, it sets the state to rendering through atomic comparison and swap operations, marking that the image is being used by the command list;

[0043] After the command list is recorded, DXVK associates and saves the Vulkan command buffer, dependency chain nodes, the corresponding image rendering completion semaphore, and the image index, establishing the binding relationship between the command buffer, dependency nodes, semaphores, and images.

[0044] The dependency chain node is a data structure that stores all synchronization information from a single submission to the rendering process. It is used to carry the rendering synchronization dependencies corresponding to this submission and records the rendering completion semaphore, image index, synchronization resource identifier, and waiting conditions. The dependency chain node is configured with corresponding linked list pointers according to different access schemes. When a mutex lock scheme is used, the node is configured with a predecessor pointer and a successor pointer. When an atomic lock-free access scheme is used, the node is configured with only a predecessor pointer. The dependency chain node is connected to the dependency chain of its D3D device instance and establishes a runtime association with the two-level semaphore synchronization agent.

[0045] Specifically, DXVK completes the binding of the command list and rendering synchronization dependencies. If the command list is used for swap chain image rendering, it reads the global swap chain synchronization context to obtain the semaphore identifier of the previous frame and configures it as the waiting semaphore for the current command buffer. It inserts resource barriers to ensure that the image resource access state matches the rendering operation of the previous frame, completing the switching of the image from the rendering state to the renderable state. Through atomic operations, it points the preorder pointer of the current dependency chain node to the tail node of the dependency chain and updates the tail pointer of the dependency chain to this node, thereby completing the construction of the lock-free dependency chain. The presentation synchronization dependency is a set of timing constraints corresponding to a single submission and presentation process, including GPU local synchronization constraints and frame-level global synchronization constraints. The GPU local synchronization constraints are derived from the Vulkan memory barrier converted from the D3D resource barrier and the semaphore wait conditions between rendering and submission, and are used to ensure the legality of GPU internal resource access and instruction execution order. The frame-level global synchronization constraints require that after the image is submitted for presentation, it must wait for the kernel's two-level semaphore synchronization agent to report the display hardware scan output completion event before the end of the presentation process is determined. In multi-frame and multi-swap chain scenarios, subsequent tasks can wait for the completion conditions of previous tasks based on this presentation synchronization dependency to avoid frame timing disorder and GPU resource access race conditions.

[0046] Furthermore, when the D3D application performs a command list reset operation, DXVK performs the following corresponding processing: it checks the state of the semaphores previously bound to the command list, returns triggered semaphores to the semaphore pool's free list, and marks untriggered semaphores as pending recycling, which will be automatically recycled after rendering ends; it clears the preorder and postorder pointers of dependent chain nodes and resets the node state to ready; if there is an anomaly in the associated image, it waits for all operations on the image to be completed and restores the image state to free to prevent resource leaks.

[0047] In particular, DXVK binds D3D resource barriers with rendering synchronization: for resource barriers that perform image layout transformations, the rendering completion semaphore of the corresponding image is set as the barrier-associated semaphore, ensuring that the rendering semaphore is activated only after the image layout transformation is completed; for resource barriers that access shared resources in multiple threads, an additional mutex semaphore is added to avoid rendering anomalies caused by resource contention.

[0048] Step 5: The D3D application initiates a command list submission request through the D3D command queue. DXVK intercepts this call, obtains the list of command buffers to be submitted, associated dependency chain nodes, the corresponding image rendering completion semaphore, and the image index. It handles multi-threaded concurrent submission scenarios, constructs a multi-threaded lock-free dependency chain, and completes command stream serialization based on the lock-free dependency chain. Then, it constructs Vulkan command submission configuration information and submits the Vulkan command buffer. The D3D application triggers image rendering. DXVK intercepts the call, parses and transforms rendering-related parameters to generate Vulkan rendering operations, and establishes a runtime association with the initialized two-level semaphore synchronization proxy. It parses rendering configuration parameters, processes vertical synchronization control parameters, and if the application has multiple exchange chains, performs multi-exchange chain synchronization processing. It assembles Vulkan rendering configuration information, submits a rendering request through the Vulkan rendering interface, and queues the image output task in the rendering queue. After submission, it performs an atomic state update on the CPU side. Subsequently, it asynchronously waits for the display hardware to complete image scanning and output, triggers the two-level semaphore proxy event, and then performs the final update of the image state.

[0049] Specifically, for rendering calls, DXVK parses the rendering configuration parameters: When configured for no-wait mode, the event polling timeout is set to zero, and the system returns success directly without blocking the rendering completion process, marking the corresponding image as skipping the rendering completion wait; when configured for restart mode, a custom kernel call is used to reset the corresponding entry in the kernel mapping table, rebinding the rendering completion semaphore and event FD, and resetting the image state to unrendered; when configured for stereoscopic rendering mode, independent semaphore and event FD flags are assigned to the left and right eye images respectively, bound to the same display controller, and the overall rendering is considered complete only when both left and right eye rendering completion events are triggered; when configured for delayed rendering mode, the current rendering task is added to a delayed queue, waiting to be submitted in batches during the next rendering call, reducing the number of Vulkan rendering interface calls.

[0050] Handling vertical synchronization control parameters: When an application enables vertical synchronization, it sends the configuration to the kernel, and the kernel only triggers the rendering completion event after the display's vertical blanking signal arrives; when an application disables vertical synchronization, it notifies the kernel to trigger the event immediately after the image scanning output is complete; when an application enables adaptive vertical synchronization, it sends an adaptive mode flag to the kernel, and the kernel dynamically adjusts the event triggering timing based on the real-time frame rate. Vertical synchronization is enabled when the frame rate is higher than the display refresh rate, and disabled when the frame rate is lower than the refresh rate.

[0051] If the application has multiple exchange chains, perform multi-exchange chain synchronization processing: read the current image index and rendering completion semaphore of all exchange chains, build global rendering dependencies, and the rendering operation of the main exchange chain needs to wait for the rendering completion signals of all child exchange chains; register the multi-exchange chain binding relationship with the kernel through a custom kernel call to ensure that the rendering completion events of all exchange chains are triggered synchronously.

[0052] Assemble Vulkan rendering configuration information: Specify the target Vulkan swap chain and the corresponding image index; Set the wait semaphore to the rendering completion semaphore of the current image to ensure that the rendering operation must wait for the rendering command to be executed before it will be executed; Obtain the corresponding Vulkan rendering mode based on the D3D swap effect mapping; Due to the lack of corresponding Vulkan extension support, the use of the native Vulkan rendering completion semaphore parameter is abandoned, and instead, the rendering completion notification is implemented by relying on a two-level semaphore synchronization proxy.

[0053] Call the Vulkan rendering interface to submit a rendering request. After submission, perform an atomic state update: modify the corresponding state bit in the image state array to mark the image as being rendered and the rendering command as having been submitted; collect the rendering submission timestamp and store it in the rendering history queue; atomically increment the rendering count value for subsequent D3D upper-layer state queries.

[0054] Furthermore, after the display engine completes image scanning and output, the display controller driver generates a hardware interrupt. The interrupt handler reads the current frame buffer identifier, the display controller identifier, and the hardware scan completion timestamp. It then obtains the corresponding semaphore identifier, event FD identifier, and semaphore status through the presentation event proxy table. If the semaphore has not yet been triggered, data is written to the corresponding event FD to wake up a user-mode readable event. If the application has vertical synchronization enabled, it waits for the display's vertical synchronization signal to arrive before triggering the event writing, aligning the presentation action with the display refresh cycle. Finally, it updates the semaphore status in the presentation event proxy table to indicate that it has been triggered and records the completion timestamp.

[0055] Furthermore, the kernel also provides a timeout detection mechanism. When the submitted image exceeds the preset timeout threshold and the scanning output is not completed, an exception flag is written to the event FD, and the exception status bit of the mapping table is updated.

[0056] The user-space proxy layer modifies DXVK as follows: During the swap chain initialization phase, DXVK creates an event polling instance, adds the event FDs of all swap chain images to the polling instance, and configures an edge-triggered mode to prevent repeated event wake-ups. After submitting a rendering request, DXVK listens for readable events in the event FD for a preset timeout threshold. Upon capturing an event, it reads the data from the event FD. In normal completion scenarios, it sets the rendering completion semaphore of the corresponding image to the triggered state, simulating a rendering completion signal. In timeout exception scenarios, it marks the corresponding image as an exception and jumps to the exception handling process. In other hardware exception scenarios, it records an exception log and resets the semaphore and event FD after the GPU device becomes idle. User space can also query the semaphore status in the kernel mapping table through custom kernel calls. When the kernel marks a semaphore as triggered but the user-space semaphore is not effective, it performs a forced trigger operation to prevent synchronization loss.

[0057] DXVK constructs a multi-threaded, lock-free dependency chain: each committing thread obtains the current tail node of the dependency chain through an atomic comparison-swap operation; the preorder pointer of the current dependency chain node is set to the tail node, and then the tail pointer of the dependency chain is updated to the current node through an atomic comparison-swap operation, completing the atomic insertion of the dependency chain node; when multi-threaded concurrency causes the atomic operation to fail, the thread rereads the tail node information, and performs a spin wait after the retry fails, reducing CPU consumption and avoiding invalid busy waiting.

[0058] Construct Vulkan command submission configuration information: If the current dependency chain node has a predecessor node, add the semaphore bound to the predecessor node to the waiting semaphore list and configure the pipeline waiting conditions to ensure that the command in this frame can only be executed after the previous frame has been rendered; fill the Vulkan command buffer to be executed into the command buffer list; add the rendering completion semaphore corresponding to the current image to the semaphore list and set the corresponding pipeline signal trigger conditions.

[0059] Submit the Vulkan command buffer. After the submission is complete, perform a series of atomic operations in the specified memory order: update the dependency chain node status to ready; modify the corresponding bit in the image status array to mark that the image has been submitted and the rendering work is finished; update the index of the currently rendered image in the global synchronization context of the exchange chain and record the timestamp of this submission.

[0060] Furthermore, multi-threaded commit performance optimization is implemented: command buffers belonging to the same image are batch-processed and merged into a single commit call, reducing driver call overhead; multiple dependency chain node caches are pre-allocated to eliminate dynamic memory allocation during the commit phase; differentiated memory ordering is used, with dependency chain insertion using release-acquisition memory ordering and status query using loose memory ordering, reducing the overhead caused by CPU cache consistency while ensuring the correctness of synchronization logic.

[0061] Example:

[0062] This embodiment employs the Direct3D implicit synchronization implementation method based on a two-level semaphore synchronization proxy provided by this invention. By modifying the source code of the Linux kernel DRM subsystem and DXVK translation layer, a five-level collaborative mechanism is constructed, consisting of kernel-mode hardware rendering event capture, a two-level semaphore synchronization proxy, atomic tracking of the swap chain image lifecycle, a lock-free dependency chain for multi-threaded command streams, and exception tolerance and resource reclamation. This mechanism maps the implicit synchronization semantics of D3D to explicit synchronization operations in Vulkan stage by stage, simulating the core functionality of the VK_KHR_present_wait extension. Simultaneously, through lock-free data structures, semaphore pooling, and memory order optimization, the mechanism ensures multi-threaded concurrency performance and stability under abnormal scenarios, achieving the goals of accurate synchronization, high performance, and reliable fault tolerance. The specific implementation process includes:

[0063] The S1 and D3D device initialization Vulkan mapping and synchronization resource pool pre-configuration correspond to the process of D3D application initializing the rendering device. DXVK needs to create the Vulkan device, synchronization resource pool, and kernel-mode proxy initialization.

[0064] DXVK receives device creation parameters from the D3D application, such as feature level and debug flags, creates a Vulkan instance and device, and queries the Vulkan feature set supported by the GPU. After confirming that the VK_KHR_present_wait extension is not supported, it activates the synchronous proxy mode in this embodiment.

[0065] Initialize the user-space synchronization resource pool. Create a Vulkan semaphore pool PresentSemaphorePool, pre-allocating 32 Vulkan binary semaphores, supporting dynamic expansion. Each semaphore is associated with a unique ID, denoted as SemaphoreID, and managed using a free list, FreeList. List operations are implemented using atomic CAS for lock-free access.

[0066] Create a kernel event FD pool FlipEventFDPool: pre-allocate 32 event FDs, each FD is associated with a unique FD-ID, which corresponds one-to-one with the SemaphoreID in the semaphore pool, forming a mapping table SyncMap from SemaphoreID to FD-ID. The mapping table is stored in an array to reduce access complexity.

[0067] Initialize atomic counters SemaphoreNextID and FDNextID to allocate new synchronization resource IDs and avoid ID conflicts.

[0068] Initialize kernel-mode two-level proxy: DXVK sends a proxy initialization request to the kernel DRM subsystem through the custom interface DRM IOCTL (DRM_IOCTL_PROXY_INIT). DRM_IOCTL_PROXY_INIT is a custom control code. This proxy initialization request carries the initial mapping relationship of SyncMap, including SemaphoreID, FD-ID, and Vulkan device handle.

[0069] The kernel DRM subsystem creates a presentation event proxy table, FlipProxyTable. The table entries include fields such as SemaphoreID, FD-ID, FB-ID, CRTC-ID, semaphore status, and timeout. Access to the table entries is protected by a spinlock. The semaphore status includes both untriggered and triggered states to avoid multi-process contention.

[0070] Initialize the multi-threaded exception handling context ThreadExceptionContext: Maintain the thread registration list ThreadRegistry, recording the thread ID, thread state, and associated synchronization resource ID of all threads participating in command submission. Thread states include running, exception, and exit. Associated synchronization resource IDs include SemaphoreID and FD-ID. Register exception signal handling functions to capture crash signals such as SIGSEGV. The signal handling functions only mark the crashed thread as an exception and do not perform complex resource reclamation operations. Specific exception detection worker threads detect exception marks, thereby triggering the subsequent resource reclamation process. Initialize the dependency chain breakpoint repair counter DependencyBreakCounter to mark broken dependency chain nodes and trigger repair logic.

[0071] Initialize performance optimization parameters: Set the semaphore pool expansion threshold, and expand by 50% when the number of idle semaphores is less than 10% of the total capacity; configure the epoll instance to edge-triggered EPOLLET mode to reduce the number of event wake-ups; define three memory ordering strategies: use memory_order_relaxed for status queries, use memory_order_acquire / release for dependency transitivity, and use memory_order_seq_cst for exception marking.

[0072] The Vulkan mapping and image state binding during the initialization of the S2 and D3D exchange chains correspond to the process of initializing the exchange chain in a D3D application. DXVK needs to create a Vulkan exchange chain and a corresponding image state tracking structure, and bind resources in the synchronization resource pool.

[0073] DXVK receives swap chain creation parameters from D3D applications, including image resolution, format, buffer size, rendering mode, SwapEffect, etc., and calls vkCreateSwapchainKHR to create a Vulkan swap chain. At the same time, it obtains the fixed refresh rate or dynamic refresh rate range of the display, calculates the rendering completion timeout threshold, which is set to 1.5 times the single frame period by default and is updated in real time in dynamic refresh rate scenarios.

[0074] For each swap chain image, perform the following binding operations: allocate one Vulkan semaphore, PresentCompleteSemaphore, from PresentSemaphorePool and record its SemaphoreID; allocate one event FD, denoted as FlipCompleteEventFD, from FlipEventFDPool and record its FD-ID; register the binding relationship between SemaphoreID, FD-ID, FB-ID, and CRTC-ID with the kernel FlipProxyTable through the custom DRMIOCTL (DRM_IOCTL_PROXY_BIND) extended by this invention, where FB-ID is the current swap chain image. The frame buffer ID of the chained image, CRTC-ID is the display controller ID associated with the exchange chain; initialize the 32-bit atomic state register ImageState, with the initial value set to 0 to indicate the idle state. The state bits are defined as follows: bit0 is 0 for idle and 1 for acquired; bit1 is 0 for not rendered and 1 for rendering; bit2 is 0 for not committed and 1 for committed; bit3 is 0 for not rendered and 1 for rendering; bit4 is 0 for incomplete and 1 for completed; bit5 is 0 for normal and 1 for abnormal; bit6 is 0 for no dependency and 1 for dependency not satisfied; bit7 is 0 for resource unlocked and 1 for resource locked.

[0075] DXVK creates a global synchronization context for the swapchain, SwapchainSyncContext, which contains the following core data structures: an atomic variable CurrentImageIndex, recording the index of the currently rendered image; an array PresentSemaphoreArray, storing the PresentCompleteSemaphore and SemaphoreID of all swapchain images; an array EventFDArray, storing the FlipCompleteEventFD and FD-ID of all swapchain images; an array ImageStateArray, storing the atomic state registers of all swapchain images; a lock-free dependency chain head pointer DependencyChainHead, pointing to the currently pending command flow dependency node; an atomic variable PresentCounter, recording the total number of renderings for D3D state lookup; and a presentation history queue PresentHistoryQueue, storing presentation timing data for the most recent 16 frames, including submission time, completion time, and VSYNC status. This queue uses a circular queue structure, and access is achieved through atomic operations.

[0076] The state mapping logic for handling the D3D swap effect (SwapEffect) is used to simulate the semantics of the DXGI swap chain behavior: If it is the DXGI_SWAP_EFFECT_DISCARD bit block copy mode, the state is automatically reset to idle after the image is rendered, without waiting for the application to release it; if it is the DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL flip mode, the state is reset only when the next frame is acquired after the image is rendered, ensuring that the historical background buffer data is not accidentally overwritten; if it is the DXGI_SWAP_EFFECT_FLIP_DISCARD flip-discard mode, an additional resource barrier semaphore is bound to ensure that the image data is released as soon as possible after rendering, reducing video memory usage.

[0077] The Vulkan mapping and synchronization dependency pre-binding for S3 and D3D command list creation and reset corresponds to the process of creating or resetting the command list in D3D applications. DXVK needs to bind rendering synchronization dependencies to ensure the consistency of the order of command list execution and rendering operations.

[0078] DXVK receives a command list creation request from a D3D application, calls vkAllocateCommandBuffers to allocate a Vulkan command buffer, VkCommandBuffer, and simultaneously allocates a dependency chain node, DependencyNode, for each command list. The node contains the following fields: a pointer to the preceding dependency node, PrevNode; a pointer to the following dependency node, NextNode; the associated SemaphoreID (i.e., the ID of the preceding rendering completion semaphore); a command buffer handle, CmdBuffer; the associated image index, ImageIndex; and an atomic state flag, NodeState, where the atomic state flag has a value of 0 indicating not ready, 1 indicating ready, 2 indicating execution, and 3 indicating completion.

[0079] When the D3D application resets the command list, DXVK performs the following operations: reads the PresentCompleteSemaphore status flag maintained by the software layer; if it is marked as triggered, it is returned to the free list of PresentSemaphorePool; if it is marked as untriggered, it is marked as pending recycling and will be automatically returned after rendering is complete; cleans up the preorder and postorder pointers of dependent chain nodes and resets NodeState to not ready; if the image associated with the command list is in an abnormal state, it calls vkQueueWaitIdle to wait for all incomplete operations on the corresponding queue to be completed, and resets the image state to idle to avoid resource leaks.

[0080] Binding command list and rendering synchronization dependencies: If the current command list is used to render the swap chain image, obtain the SemaphoreID (PrevSemaphoreID) of the previous frame from SwapchainSyncContext, configure this semaphore as the waiting semaphore for subsequent queue submissions, and specify the waiting pipeline stage in VkSubmitInfo; call vkCmdPipelineBarrier to add a resource barrier to ensure that the access permissions of the image resources are compatible with the rendering operation of the previous frame. For example, after the rendering of the previous frame is completed, the image resources are converted from rendering to renderable; set the PrevNode of the current dependency chain node to the tail node of the dependency chain through a CAS atomic operation, update the tail pointer of the dependency chain to the current node, and realize lock-free dependency chain construction.

[0081] The S4 and D3D command lists record Vulkan mappings and resource barriers for synchronization. Corresponding to the process of recording rendering commands in D3D applications, DXVK needs to convert D3D commands into Vulkan command buffers and bind them to presentation synchronization semaphores.

[0082] DXVK receives command list recording requests from D3D applications, parses resource access and pipeline state settings in the command stream, converts them into corresponding Vulkan calls, and records them in the Vulkan command buffer VkCommandBuffer. Resource access includes vertex buffer reading and render target writing, while pipeline state settings include blending mode and depth testing.

[0083] Handling the binding of D3D resource barriers and rendering synchronization: If the resource barrier type is a resource state transition barrier (D3D_RESOURCE_BARRIER_TYPE_TRANSITION) and involves layout transformations of swap-chained images, such as from resource state-render target (D3D_RESOURCE_STATE_RENDER_TARGET) to resource state-presentation (D3D_RESOURCE_STATE_PRESENT), then DXVK translates it into a Vulkan image memory barrier and writes it to the command buffer. Instead of directly binding semaphores within the resource barrier, the current image's PresentCompleteSemaphore is configured in the subsequent vkQueueSubmit semaphore list, associated with the corresponding pipeline stage, ensuring that the rendering semaphore is activated only after the GPU commands, including layout transformations, have been executed. If the resource barrier type is a UAV barrier (i.e., an unordered view access barrier D3D_RESOURCE_BARRIER_TYPE_UAV) and involves multi-threaded shared resource access, the DXVK translation layer adds an additional mutex semaphore for GPU-side synchronization. This mutex semaphore is not part of the D3D memory barrier. Native UAV barrier capability to avoid rendering errors caused by resource contention.

[0084] If the command list contains render target write operations, meaning the current image is the render target, DXVK

[0085] Add a semaphore signaling operation to the end of the command buffer: specify PresentCompleteSemaphore[ImageIndex] as the semaphore to be signaled, set the wait condition to the semaphore to be signaled when PresentCompleteSemaphore[ImageIndex] is configured as vkQueueSubmit, specify the signal activation pipeline stage as VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, and ensure that the semaphore's pending state is activated after the rendering command is completed.

[0086] The atomic operation `memory_order_relaxed` pre-reads bit 1 of `ImageStateArray[ImageIndex]`. If the pre-read result is 0, the atomic CAS operation `memory_order_acq_rel` sets bit 1 to 1, marking that the current image is being accessed by the command list, thus preventing other threads from modifying the resource state of the image at the same time.

[0087] After the command list is recorded, DXVK associates and stores the Vulkan command buffer, dependency chain node, PresentCompleteSemaphore [ImageIndex], and ImageIndex, forming a binding relationship between the command buffer, dependency node, semaphore, and image, providing a synchronization context for subsequent command submissions.

[0088] The Vulkan mapping and multi-threaded lock-free dependency chain construction of S5 and D3D command queues correspond to the process of D3D applications submitting command lists. DXVK needs to handle multi-threaded concurrent submissions and implement command stream serialization through lock-free dependency chains to ensure that the execution order is consistent with the rendering synchronization dependency.

[0089] DXVK receives command queue submission requests from D3D applications and obtains the currently submitted command buffer list, the associated dependency chain node DependencyNode, the semaphore PresentCompleteSemaphore [ImageIndex], and the image index ImageIndex.

[0090] Multi-threaded lock-free dependency chain construction: Each committing thread reads the tail pointer TailNode of the current dependency chain through the atomic load operation memory_order_acquire; sets the PrevNode of the current dependency chain node as TailNode, and updates the tail pointer of the dependency chain to the current node through an atomic CAS operation using memory_order_acq_rel, thus achieving atomic insertion of the dependency chain; if multiple threads commit at the same time, the thread that fails the CAS operation needs to reacquire TailNode, with a maximum of 3 retries. If more than 3 retries are made, a spin-wait is used to reduce CPU overhead and avoid busy waiting.

[0091] The Vulkan command submission information structure VkSubmitInfo is constructed as follows: It configures a list of waiting semaphores. If the PrevNode of the current dependency chain node is not empty, it adds the Vulkan semaphore corresponding to the SemaphoreID associated with the PrevNode and specifies it as the color attachment output pipeline stage VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT in the waiting target pipeline stage mask pWaitDstStageMask, ensuring that the current frame command is executed only after the previous frame has finished rendering. It also includes a command buffer list, adding the currently submitted Vulkan command buffer; and a semaphore list, adding the PresentCompleteSemaphore [ImageIndex] of the current image, with the corresponding signal-activated pipeline stage set to the color attachment output pipeline stage VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT.

[0092] The Vulkan interface `vkQueueSubmit` is called to submit the command buffer to the GPU queue. After the CPU side completes the command enqueueing, the following host-side atomic state updates are performed. At this time, the GPU has not yet completed rendering: the `NodeState` of the dependent chain node is updated with `memory_order_release` to indicate that it is ready; `memory_order_relaxed` is used to update bit2 of `ImageStateArray[ImageIndex]` to 1 to indicate that it has been submitted and bit1 to 0 to indicate that the host side has marked the rendering stage as complete; the spin lock `SyncLock` is acquired, and the `CurrentImageIndex` in `SwapchainSyncContext` is updated to the current `ImageIndex`; the `clock_gettime` system interface is called, and the timestamp is obtained using the monotonic clock `CLOCK_MONOTONIC` and recorded as the submission time of this frame.

[0093] Multi-threaded submission performance optimization: A command buffer batch processing mechanism is adopted. When multiple threads submit command buffers associated with the same image, they are merged into a single vkQueueSubmit call, reducing driver call overhead; Dependency chain nodes are pre-allocated, with 16 dependency chain node caches allocated in advance to avoid dynamic memory allocation during submission; Precise memory order control is implemented, with CAS atomic modifications for dependency chain insertion using memory_order_acq_rel, critical shared data loading and reading using memory_order_acquire, and non-synchronous status queries using memory_order_relaxed. Status queries use relaxed memory order, ensuring synchronization correctness while minimizing CPU cache consistency overhead.

[0094] The implementation of S6 and the two-level semaphore synchronization proxy is the core of implicit synchronization simulation. It realizes the proxy from kernel-mode presentation events to user-mode Vulkan semaphores, simulating the semaphore triggering mechanism of VK_KHR_present_wait.

[0095] The kernel-mode proxy layer is implemented by modifying the DRM subsystem: The kernel DRM subsystem maintains the newly added kernel hash table FlipProxyTable in this embodiment. The table entries adopt a hash table structure, using FB-ID and CRTC-ID as keys to quickly look up the corresponding SemaphoreID and FD-ID. When the display engine completes the scanning and output of the current image, that is, when all image data has been transmitted to the display, the CRTC driver triggers a hardware interrupt. The interrupt handler reads the FB-ID, CRTC-ID, and scan completion timestamp of the current scan output; it then queries FlipProxyTable using FB-ID and CRTC-ID as keys to obtain the corresponding SemaphoreID and FD-ID. The emaphoreID, FD-ID, and semaphore status are recorded. If the semaphore status is not triggered, 1 byte of data with a value of 1 is written to FlipCompleteEventFD via the eventfd_write function, triggering the EPOLLIN event in user mode. If the D3D application has VSYNC enabled, the page flipping operation itself is completed during the vertical blanking period of the VBLank timing. The flipping completion interrupt is triggered at the VBLank time, and then the eventfd_signal operation is executed to ensure that the rendering operation is aligned with the display refresh cycle. The semaphore status of the FlipProxyTable entry is updated to triggered, and the completion timestamp is recorded.

[0096] Kernel-mode timeout detection: If the image rendering operation has not completed the scanning output after the calculated timeout threshold has been exceeded after submission, the eventfd_write operation is automatically triggered to write the exception flag and update the exception status bit of the table entry.

[0097] Modify the DXVK implementation of the user-space proxy layer: During swap chain initialization, DXVK creates an epoll file descriptor instance EpollFD, adds the FlipCompleteEventFD of all swap chain images to the epoll instance, and sets the event type to EPOLLIN | EPOLLET (read event, edge-triggered mode) to avoid repeated wake-ups; after DXVK submits a rendering request, it calls the epoll wait system call epoll_wait, passing in the epoll instance and struct The `epoll_event` array is used to set `maxevents` to 1 and `timeout` to the calculated timeout threshold. It listens for readable events in `FlipCompleteEventFD`. When `epoll_wait` returns 0, it indicates a timeout. If a readable event is detected, the 64-bit counter value of the `eventfd` is obtained from `FlipCompleteEventFD`. If the counter value is 1, indicating that the kernel reported normal presentation completion, the `PresentCompleteSemaphore` state flag maintained by the software layer is updated to indicate that it has been triggered, and the software simulates the presentation completion notification effect of the extended `VK_KHR_present_wait`. If `epoll_wait` returns 0, indicating a timeout, bit 5 of `ImageStateArray[ImageIndex]` is set to 1 to indicate an exception, triggering the exception handling process. If other IO read hardware exceptions occur, an exception log is recorded, the device idle wait function `vkDeviceWaitIdle` is called to wait for all incomplete operations on the logical device to complete, and the software semaphore flag and event FD state are reset.

[0098] Semaphore state synchronization: User space queries the kernel-space flip proxy table FlipProxyTable for semaphore state through the custom interface DRM IOCTL (DRM_IOCTL_PROXY_QUERY). If the kernel space marks it as triggered, but the semaphore state maintained by the user space software has not yet been updated to triggered, the user space software layer PresentCompleteSemaphore state is forcibly updated to triggered. This is only used for host-side software logic judgment and does not perform host-side signaling operations on Vulkan hardware semaphore objects, thus avoiding synchronization omissions caused by the loss of kernel-space and user-space notification links.

[0099] Consistency guarantee of dual-level proxy: The kernel and user spaces maintain a unified semaphore state bitmap, with each 16 semaphores corresponding to a 64-bit atomic bitmap, allowing for fast querying of semaphore states through bitwise operations; Semaphore triggering adopts a two-stage mechanism of kernel-level marking followed by user-level confirmation. After the kernel completes the flip, it first marks the kernel-side state, and the user space confirms the user-side state after receiving the event or query, avoiding signal loss; When a Vulkan semaphore is reset and returned to the resource pool by the user space, DXVK calls the custom interface DRM_IOCTL_PROXY_RESET to notify the kernel space to update the corresponding entry in FlipProxyTable and the kernel bitmap state, ensuring consistency between the kernel and user spaces.

[0100] The Vulkan mapping and presentation operations called by S7 and D3D Present / Present1 are submitted, corresponding to the process of D3D application triggering image presentation. DXVK needs to convert the Present parameter into a Vulkan presentation operation and associate it with a two-level semaphore proxy.

[0101] For the Present1 call, DXVK parses the presentation parameter structure DXGI_PRESENT_PARAMETERS: If the non-waiting flag DXGI_PRESENT_DO_NOT_WAIT is specified, then the epoll_wait timeout is set to 0, adopting non-blocking mode and waiting for presentation to complete without blocking; if non-blocking detection indicates that presentation has not yet completed, then a simulated return of the DXGI_ERROR_WAS_STILL_DRAWING error code is made, and the ImageStateArray[ImageIndex] is marked. Bit 4 is 1; if the restart rendering flag DXGI_PRESENT_RESTART is specified, then the FlipProxyTable entry of the current image is reset through the custom DRM reset IOCTL interface DRM_IOCTL_PROXY_RESET in this embodiment, the PresentCompleteSemaphore and FlipCompleteEventFD are rebound, and the ImageState is reset to not rendered; if the current scene is a stereoscopic rendering exchange chain DXGI_PRESENT_STEREO, DXVK assigns independent SemaphoreID and FD-ID to the left and right eye images respectively, and the two are bound to the same CRTC-ID to achieve stereoscopic rendering synchronization. It is necessary to wait for the rendering completion events of the left and right eye images to be reported before the current stereoscopic frame rendering process is considered to be over; a left and right eye rendering delay queue mechanism can be used to merge the two rendering requests and reduce the number of Vulkan rendering interface calls. This queue mechanism is a new capability added to the DXVK translation layer and is not controlled by the native DXGI flag.

[0102] Processing VSYNC control parameters:

[0103] If the D3D application has VSYNC enabled, the synchronization mode parameters are sent to the kernel proxy layer through the custom DRM vertical synchronization trigger configuration IOCTL interface DRM_IOCTL_MODE_SET_VSYNC_TRIGGER in this embodiment. If the D3D application has VSYNC enabled, the vertical synchronization enable parameter VSYNC_ENABLE=1 is passed in, and the kernel triggers the presentation completion event after the vertical synchronization signal VBLANK timing for page flipping is completed. If VSYNC is disabled, the parameter VSYNC_ENABLE=0 is passed in, and the kernel triggers the event immediately after the image scanning output is completed. When Present... When calling DXGI_PRESENT_ALLOW_TEARING with the tearing allow flag, DXVK calculates the current frame rendering frame rate in user space and compares it with the display refresh rate. When the custom adaptive vertical synchronization logic in this embodiment is enabled, the adaptive vertical synchronization mode parameter VSYNC_ADAPTIVE=1 is passed to the kernel. The frame rate judgment logic is completed by the user-space DXVK, and the judgment result is sent to the kernel. The kernel selects a synchronization strategy based on the sent judgment result: VSYNC synchronization is used when the frame rate is higher than the display refresh rate, and VSYNC is turned off when the frame rate is lower than the display refresh rate, correspondingly controlling the triggering timing of the rendering completion event.

[0104] If the application has multiple exchange chains, multi-exchange chain synchronization is handled as follows: obtain the current image index and PresentCompleteSemaphore of all exchange chains; construct global rendering dependencies, and the rendering completion determination of the main exchange chain needs to wait for the rendering completion events of all child exchange chains; call the custom multi-exchange chain binding IOCTL interface DRM_IOCTL_PROXY_MULTI_BIND to register the multi-exchange chain binding dependency relationship with the kernel; the kernel collects the rendering completion events of each child exchange chain, and only after all child exchange chain completion events have been reported will the overall completion notification of the main exchange chain be triggered. Construct the Vulkan presentation information structure VkPresentInfoKHR: specify the swap chain as the current Vulkan swap chain, and the image index as ImageIndex; configure the wait semaphore list as the rendering completion semaphore to ensure that the presentation operation is only executed after the rendering command is completed; map the presentation mode VkPresentModeKHR according to the presentation mode of the D3D swap chain: map the DXGI flip sequence mode DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL to the first-in-first-out presentation mode VK_PRESENT_MODE_FIFO_KHR, and map the DXGI discard mode DXGI_SWAP_EFFECT_DISCARD to the immediate presentation mode VK_PRESENT_MODE_IMMEDIATE_KHR; this embodiment ignores the native Vulkan presentation completion semaphore parameters, and instead relies on the kernel-user space two-level semaphore proxy of this embodiment to obtain the display scan completion notification. The Vulkan queue presentation interface vkQueuePresentKHR is called to submit a presentation request. After the CPU completes the enqueueing of the presentation request, but the display has not yet completed the image scanning and output, the following host-side atomic operations are performed: bit 3 of ImageStateArray[ImageIndex] is updated to 1 to indicate that presentation is in progress, and bit 2 is set to 0 to clear the submitted flag; the presentation submission timestamp is recorded and stored in PresentHistoryQueue; the atomic variable PresentCounter is incremented using memory order_relaxed for subsequent D3D application status queries.

[0105] S8. User-mode rendering is completed and synchronization and multi-threaded state consistency are maintained. This corresponds to the process of completing DXVK perception rendering. The core is to handle two-level semaphore proxy events, update the image state, and ensure multi-threaded synchronization.

[0106] After DXVK's epoll_wait detects the EPOLLIN event of FlipCompleteEventFD, it performs the following operations: reads the 64-bit event count value of eventfd and records the frame completion timestamp; if it is determined to be a normal completion, it updates the PresentCompleteSemaphore[ImageIndex] status flag maintained by the user-space software layer to indicate that it has been triggered, and does not perform host-side signaling operations on the Vulkan binary semaphore hardware object; if it is determined to be an exception, it triggers the exception handling process and skips all subsequent status updates. It updates the various status bits of ImageStateArray[ImageIndex] using atomic operations with memory_order_release: bit4 is set to 1 to indicate completion, bit3 is set to 0 to clear the rendering flag, and bit0 is set to 0 to release the acquisition status; if the swap chain effect is DXGI discard mode DXGI_SWAP_EFFECT_DISCARD, bit7 is set to 0 to release the resource lock; bit5 is cleared to remove the exception flag, restoring the image software state to normal. Multi-threaded state synchronization: Under the protection of a mutex lock, the waiting thread list of the ThreadExceptionContext is checked; if other threads are blocked waiting for the current image to be rendered, the POSIX condition variable pthread_cond_broadcast is called to wake up all waiting threads and pass a synchronization signal that the image rendering is complete; the NodeState of the current dependent chain node is set to complete; the readiness judgment of subsequent dependent nodes is not performed by traversing the linked list in the epoll event loop, but is handled by the commit and retry path of the commit thread to avoid blocking the IO event loop. Update the presentation history queue: The submission time, completion time, VSYNC status, image index and other information of the current frame are stored in the PresentHistoryQueue; if the queue is full, the oldest frame data in the queue is overwritten to ensure that the queue always keeps the frame timing information of the most recent 16 frames.

[0107] DXVK sets a mutex lock on the dependency chain corresponding to the D3D device instance; when performing dependency chain node access, removal, or traversal operations, the mutex lock is acquired, and the mutex lock is released after the operation is completed, to avoid data corruption caused by concurrent modification of the doubly linked list by multiple threads; the shared state variables in the swap chain image state register and the swap chain global synchronization context are protected by atomic access or locks; the epoll event polling thread runs independently, receives event notifications from the two-level semaphore synchronization agent, and accesses the synchronization object concurrently with the rendering thread.

[0108] The Vulkan mapping for S9 and D3D rendering status queries corresponds to the process of querying rendering-related statuses in D3D applications. The core is to convert the rendering information captured by the kernel into D3D-compatible query results.

[0109] When a D3D application calls IDXGISwapChain::CheckPresentTiming to query the presentation timing, DXVK performs the following operations: extracts the frame data corresponding to the current ImageIndex from PresentHistoryQueue; maps the presentation submission timestamp to PresentStartTime in DXGI_PRESENT_TIMING; maps the scan completion timestamp returned by the kernel to PresentEndTime; maps the VBLank vertical synchronization time reported by the kernel to SyncQPCTime; maps the value of PresentCounter to TotalPresentCount; and calculates the presentation latency as PresentEndTime - PresentStartTime, which is then mapped to DisplayLatency.

[0110] When a D3D application calls IDXGIOutput::GetDisplayModeList to query supported display modes, DXVK performs the following operations: obtains the list of kernel-supported display modes through the custom DRM IOCTL interface DRM_IOCTL_MODE_GET_SUPPORTED_MODES; converts the kernel display mode into a D3D DXGI_MODE_DESC structure, which includes information such as resolution, refresh rate, and format; and, in conjunction with the synchronization features supported by this invention, filters out Vulkan display modes that are compatible with D3D display modes to ensure semantic consistency of display modes.

[0111] When a D3D application calls IDXGISwapChain::GetLastPresentCount to query the number of presentations, DXVK uses memory_order_acquire to read the PresentCounter atomic value and return it, ensuring the accuracy of the query results.

[0112] When a D3D application calls ID3DCommandQueue::GetTimestampFrequency to query the timestamp frequency, DXVK calls the custom DRM timestamp frequency query IOCTL interface DRM_IOCTL_QUERY_TIMESTAMP_FREQ to obtain the kernel display hardware timestamp frequency; then it converts and aligns the hardware timestamp frequency to the CPU QPC timestamp frequency unit expected by the D3D application, and returns the converted frequency value to ensure the consistency of the unit for displaying timing queries.

[0113] S10, multi-threaded exception handling and resource reclamation, handles various abnormal scenarios in a multi-threaded environment, ensuring that DXVK does not crash, the application does not freeze, and synchronization resources are not leaked.

[0114] Program-level exception handling, such as thread crashes or exits: When the exception signal handler `ExceptionHandler` captures a thread crash signal such as `SIGSEGV` or `SIGABRT`, the signal context only records the crashed thread ID and does not perform resource release or Vulkan calls; it wakes up an independent exception handling worker thread to complete subsequent resource cleanup; the worker thread traverses the custom data structure `ThreadRegistry` in this embodiment to find the synchronization resources associated with the crashed thread, such as `SemaphoreID`, `FD-ID`, dependency chain nodes, and image indexes; for the associated `PresentCompleteSemaphore` binary semaphore, it destroys and returns it to `PresentSemaphorePool` after the device is idle. Direct reset of the interface on the host side is not supported; for the associated FlipCompleteEventFD, the custom DRM unbinding IOCTL interface DRM_IOCTL_PROXY_UNBIND is called to unbind from the kernel FlipProxyTable and return the file descriptor to FlipEventFDPool; for the associated dependency chain node, the state is marked as abnormal and the dependency chain list is repaired: the PrevNode and NextNode of the abnormal node are directly connected, and the abnormal node is skipped from the list; for the associated image, bit5 of ImageStateArray[ImageIndex] is set to 1 to mark the abnormality, vkQueueWaitIdle is called to wait for all operations in the queue to complete, and the image is reset to the idle state.

[0115] Command-level exception handling, such as command submission failure: If the vkQueueSubmit or vkQueuePresentKHR call returns a non-success value such as VK_ERROR_DEVICE_LOST or VK_ERROR_OUT_OF_DATE_KHR, then the current dependency chain node is marked as having failed to commit; if the exchange chain has expired (VK_ERROR_OUT_OF_DATE_KHR), then the Vulkan exchange chain is rebuilt, all synchronization resources are rebound, and the kernel FlipProxyTable is updated synchronously; if the device is lost (VK_ERROR_DEVICE_LOST), then the D3D device reset process is triggered, the application is notified to call ID3DDevice::Reset, all synchronization resource pools are released, and a complete reinitialization is performed.

[0116] Synchronization-level exception handling, such as semaphore wait timeout or deadlock: If epoll_wait times out, the following operations are performed: DRM_IOCTL_PROXY_QUERY is called to query the kernel-mode semaphore record status; if the kernel has already marked it as triggered, only the user-mode software layer PresentCompleteSemaphore status is forcibly updated to be marked as triggered, without performing host-side signaling operations on the Vulkan hardware semaphore object; if the kernel has not marked it as triggered, bit 5 of ImageStateArray[ImageIndex] is set to 1 to indicate an exception, the device idle wait vkDeviceWaitIdle is called to wait for all logical device operations to complete, and the relevant synchronization resources are reset; a timeout log is recorded, and the timeout threshold for the next frame is dynamically adjusted, increasing the threshold by 50% to reduce the probability of subsequent repeated timeouts. Deadlock detection: The continuous waiting time of each dependency chain node is recorded through atomic variables; if the waiting time exceeds 3 times the single frame period, a deadlock is determined, the dependency chain is forcibly reset, and all associated synchronization resources of that node are released.

[0117] Resource leak cleanup: Periodically perform resource cleanup scans, traversing the free lists of PresentSemaphorePool and FlipEventFDPool; for synchronization resources that have not been allocated for a long time, call vkDestroySemaphore or close(fd) to release them, reducing memory and file descriptor usage; traverse ImageStateArray, for images marked as abnormal and unprocessed for more than 5 frames, force reset to an idle state, releasing the corresponding video memory resources.

[0118] S11, Exchange Chain Image Reuse and Resource Optimization, corresponds to the lifecycle of exchange chain images, and its core is to ensure the secure reuse of images and efficient utilization of resources.

[0119] When the D3D application calls IDXGISwapChain::AcquireNextImage again to acquire an image, DXVK executes the following process: it calls vkAcquireNextImageKHR to obtain the index ImageIndex of the next available image; it reads the status bits of ImageStateArray[ImageIndex] through the atomic operation memory_order_acquire: if bit4 is 1, it means that the process is complete and bit5 is 0, indicating that the image has completed its previous rendering and can be used safely; if bit4 is 0, it means that the process is not complete, and it calls epoll_wait to wait for the readable event of EventFDArray[ImageIndex], with the waiting time not exceeding the calculated timeout threshold; this waiting is a new upper-level waiting logic added in this embodiment, and it is necessary to avoid timeout superposition with the internal waiting of vkAcquireNextImageKHR; if the waiting times out, it sets bit5 to 1, which is an exception flag, and calls vkQueueWaitIdle to wait for all operations in the corresponding queue to complete, forcibly setting bit4 to 1; vkQueueWaitIdle will wait for all tasks in the queue, not just a single image. After confirming that the image is available, the status bits of ImageStateArray[ImageIndex] are updated through the atomic CAS operation memory_order_release: bit0 is set to 1 to indicate that it has been acquired, bit1 is set to 0 to indicate that it has not been rendered, bit2 is set to 0 to indicate that it has not been committed, bit3 is set to 0 to indicate that it has not been presented, bit4 is set to 0 to indicate that it is not completed, and bit5 is set to 0 to indicate that it is normal. If the swap chain effect is DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, bit7 is set to 1 to indicate that the resource is locked to prevent other threads from modifying the image resource.

[0120] Resource optimization operations: For images that have not been reused for a long time, such as exceeding 5 frame cycles, vkTrimCommandPool is called to release idle resources in the associated command pool, reducing video memory usage; if insufficient GPU video memory is detected by vkGetPhysicalDeviceMemoryProperties, this embodiment does not directly modify the number of images in the existing swap chain, but destroys and rebuilds the swap chain, reducing the number of images to a minimum of 2, while increasing the expansion threshold of the synchronization resource pool; provided that hardware and format conditions permit, the VK_EXT_compressed_image_transfer extension can be enabled for image copy compression optimization to reduce data transmission overhead; the image presented by the swap chain is constrained by the display output, and this compression capability is not forced to be enabled.

[0121] In summary, the above are merely preferred embodiments of the present invention and are not intended to limit the scope of protection of the present invention. Any modifications, equivalent substitutions, improvements, etc., made within the spirit and principles of the present invention should be included within the scope of protection of the present invention.

Claims

1. A Direct3D implicit synchronization implementation method based on a two-level semaphore synchronization proxy, characterized in that, Specifically, the following steps are included: During D3D application initialization, D3D device instances and D3D logical devices are created. DXVK correspondingly creates Vulkan instances and Vulkan logical devices. If the GPU supports the VK_KHR_present_wait extension, the native wait path is used for execution; otherwise, a Vulkan semaphore pool and a kernel event FD pool are created. Event FDs and Vulkan semaphores are mapped one-to-one to form the first mapping table. DXVK sends an initialization request carrying the first mapping table to the DRM subsystem, triggering a two-level semaphore synchronization agent to complete kernel-mode and user-mode initialization. The D3D application creates a D3D swap chain, and the corresponding DXVK application creates a Vulkan swap chain. The rendering completion timeout threshold is set according to the display refresh rate. Semaphores are allocated from the Vulkan semaphore pool and event FDs are allocated from the kernel event FD pool for the swap chain image. The binding relationship between semaphore identifiers, event FD identifiers, framebuffer object identifiers and screen identifiers is registered with the kernel. The event FDs are added to the epoll event polling instance. The status register of the swap chain image is set to idle. The D3D application creates a command list, and DXVK creates a corresponding Vulkan command buffer. The D3D instructions in the command list are converted into Vulkan instructions and written into the Vulkan command buffer. The D3D resource barriers in the command list are converted into Vulkan memory barriers, forming GPU local synchronization conditions. When a D3D application submits a command list, DXVK allocates a dependency chain node for the command list. This dependency chain node describes the rendering synchronization dependency corresponding to this submission. The generated GPU local synchronization conditions are added to the rendering synchronization dependency, and the rendering completion semaphore, image index, synchronization resource identifier, and waiting conditions are recorded. This dependency chain node establishes a runtime association with the two-level semaphore synchronization agent. This dependency chain node is then connected to the dependency chain of its respective D3D device instance, and the Vulkan command buffer is submitted. When a D3D application triggers image rendering, DXVK builds the Vulkan rendering configuration and submits a rendering request to add the image output task to the rendering queue. The kernel's two-level semaphore synchronization agent detects that the display hardware scan output is complete, triggers an event, and updates the corresponding exchange chain image state.

2. The Direct3D implicit synchronization implementation method according to claim 1, characterized in that, Also includes: Configure a mutex lock on the dependency chain corresponding to the D3D device instance. When performing dependency chain node access, deletion, or traversal operations on the dependency chain, acquire the mutex lock and release the mutex lock after the operation is completed. When accessing a dependency chain node, modify the predecessor and successor pointers of the dependency chain.

3. The Direct3D implicit synchronization implementation method according to claim 1, characterized in that, For different swap effect types, the swap chain images undergo adaptive state recycling processing: For DXVK swap chain images in bit block copy mode, after rendering is complete, the swap chain image is marked as idle and returned to the swap chain image pool without waiting for application release; for DXVK swap chain images in flip mode, they are not processed immediately after rendering is complete, but are marked as idle and returned to the swap chain image pool when the operation of obtaining the next frame image is performed; for DXVK swap chain images in flip-drop mode, GPU-side read and write access synchronization is completed by binding resource barrier synchronization objects, and after the kernel detects that the display hardware scan output is complete, the swap chain image is marked as idle and returned to the swap chain image pool.

4. The Direct3D implicit synchronization implementation method according to claim 1, characterized in that, When a D3D application triggers image rendering, DXVK parses the rendering configuration parameters carried in this rendering call: When configured for no-wait mode, the event polling timeout is set to zero, and the system returns success directly without blocking the rendering completion wait, marking the corresponding swap chain image as skipping the rendering completion wait logic; When configured for reset mode, the DRM subsystem's custom interface is called to reset the corresponding entry in the kernel mapping table of the two-level semaphore synchronization agent, rebinding the rendering completion semaphore and event FD, and resetting the swap chain image state to pending rendering; When configured for stereoscopic rendering mode, independent semaphore identifiers and event FD identifiers are assigned to the left and right eye images respectively and bound to the same display controller. The overall rendering is considered complete only when all rendering completion events for the left and right eyes are triggered; When configured for delayed rendering mode, the current rendering task is added to the user-space delayed queue, and all tasks in the queue are submitted in batches when the next rendering call is triggered.

5. The Direct3D implicit synchronization implementation method according to claim 1, characterized in that, When an application enables vertical synchronization, it sends the configuration to the dual-level semaphore synchronization agent. After receiving the image output task, the kernel triggers the rendering completion event only after the vertical blanking signal arrives. When an application disables vertical synchronization, it notifies the kernel to trigger the rendering completion event immediately after the image scan output is complete. When an application enables adaptive vertical synchronization, it sends an adaptive mode flag to the kernel. The kernel calculates the real-time frame rate and dynamically adjusts the event triggering timing: when the frame rate is higher than the display refresh rate, vertical synchronization is enabled, and the event is triggered only after the vertical blanking signal arrives; when the frame rate is lower than the display refresh rate, vertical synchronization is disabled, and the event is triggered immediately after the image scan output is complete.

6. The Direct3D implicit synchronization implementation method according to claim 1, characterized in that, If there are multiple swap chains under the current D3D device instance, perform multi-swap chain synchronization processing: read the current image index and rendering completion semaphore of all swap chains, build global rendering dependency relationship, and make the rendering operation of the main swap chain wait for the rendering completion signals of all sub-swap chains; The DRM subsystem's custom interface is called to register multiple exchange chain binding relationships with the kernel. Only after all bound exchange chains have completed image scanning and output will the kernel synchronously trigger the rendering completion events corresponding to all exchange chains.

7. The Direct3D implicit synchronization implementation method according to claim 1, characterized in that, After the display engine completes image scanning and output, the display controller driver generates a hardware interrupt. The interrupt handler reads the current frame buffer identifier, the display controller identifier, and the hardware scan completion timestamp, queries the rendering event proxy table, and obtains the corresponding semaphore identifier, event FD identifier, and semaphore status. If the semaphore has not yet been triggered, data is written to the corresponding event FD after the vertical synchronization constraint is met, thus waking up a user-mode readable event. When the application enables vertical synchronization, it must wait for the display's vertical blanking signal to arrive before executing the event writing, so that the rendering event is aligned with the display refresh cycle. Then update the semaphore status in the event delegate table to "triggered" and record the frame completion timestamp.

8. The Direct3D implicit synchronization implementation method according to claim 1, characterized in that, Also includes: During the initialization phase of the exchange chain, the user-space proxy layer of the two-level semaphore synchronization proxy configures the epoll event polling instance to edge-triggered mode. After submitting the rendering request, it listens for the readable event FD with a preset timeout threshold. After capturing the readable event, it sets the rendering completion semaphore of the corresponding image to the triggered state. When a timeout occurs, it marks the image as abnormal and enters the exception handling process. When a hardware anomaly occurs, logs are recorded, and semaphores and event FDs are reset once the GPU device is idle. The user-mode agent layer queries the kernel mapping table through a custom kernel call and performs a forced trigger operation when the kernel marks the semaphore as triggered but the user-mode semaphore is not effective.

9. The Direct3D implicit synchronization implementation method according to claim 1, characterized in that, The dependency chain node is connected to the dependency chain of its D3D device instance using an atomic lock-free connection method: each submitting thread reads the current tail node of the dependency chain; the preceding pointer of the dependency chain node to be connected is set to the tail node, and then an atomic comparison and swap operation is used to try to update the tail pointer of the dependency chain to the dependency chain node to be connected, thus completing the atomic connection of the dependency chain node; when multi-threaded contention causes the atomic comparison and swap operation to fail, the thread rereads the tail node information of the dependency chain and retryes. If the retry still fails after a set number of times, a spin wait is executed.

10. The Direct3D implicit synchronization implementation method according to claim 1, characterized in that, The way DXVK assembles Vulkan rendering configuration information is as follows: specify the target Vulkan swap chain and the index of the image to be rendered, set the waiting semaphore for the rendering operation to the rendering completion semaphore of the current frame so that the rendering operation is executed after the rendering command is completed; map D3D swap effects to Vulkan swap chain rendering modes and retain the internal swap effect type flags; The hardware scan output layer presentation completion notification is provided by a two-level semaphore synchronization agent.