## Description This PR is for review and integration of Direct3D 12 Rendering Pipeline into JavaFX mainline. We released three Early Access (EA) versions of this implementation while keeping the development ongoing on [JavaFX Sandbox](https://github.com/openjdk/jfx-sandbox/tree/direct3d12) and reached a stage where it is ready to be integrated into mainline. Any further work and potential fixes will be done on mainline.
At the time of writing, this PR is identical to the [JavaFX Sandbox D3D12 branch](https://github.com/openjdk/jfx-sandbox/tree/direct3d12) with only one difference - the Sandbox defaults to D3D12 backend. This PR, however, does *NOT* change the default rendering pipeline on Windows. D3D9 remains the default rendering pipeline and D3D12 is optional - it can be selected by providing `-Dprism.order=d3d12`. To verify which pipeline is actually in use `-Dprism.verbose=true` is recommended. ## Details Below are general changes introduced by the backend: ### JSL changes - Introduced `HLSL6Backend` class which translates JSL shader code into HLSL6 code. D3D12 introduced HLSL Shader Level 6 support and won't support existing HLSL shaders used with D3D9, as those are compiled for unsupported Shader Level 3. - D3D12-specific shaders are kept in `modules/javafx.graphics/src/main/native-prism-d3d12/hlsl6` - Shader compilation is done with DXC instead of FXC (FXC does not support SL6). DXC is bundled in Windows SDK which JavaFX already integrates with. - Backend also generates C++ headers with Shader resource binding information, used by the native-side ### Build changes - Added new build tasks for generation and compilation of HLSL6 shaders for D3D12 - Added tasks to compile D3D12 native backend code ### Prism changes - Added D3D12-specific Java classes (package `com.sun.prism.d3d12`) and a Java-to-JNI layer (package `com.sun.prism.d3d12.ni`) - Java implementation is mostly similar to D3D9 implementation, with only some minor changes needed to accommodate slightly different presentation behavior of the new runtime - JNI interface is relatively high level to reduce the amount of JNI calls for performance - Added a native Prism backend implementation using D3D12 runtime (stored in `modules/javafx.graphics/src/main/native-prism-d3d12`) - Written in C++ 20 - Uses only interfaces available via Windows API with no third-party libraries - WinAPI, Windows COM interface system and "barebones" Direct3D 12 API/runtime - Native layer entry-points are kept in `D3D12` namespace and stored in `(...)/native-prism-d3d12` - Responsible of exposing JNI entry point implementations and translating JNI primitives into C++ types/objects - Each `com.sun.prism.d3d12.ni` Java class has its respective C++ class as an entry point with 1:1 Java->C++ method mapping - C++-side allocates a shared_ptr instance and passes over a pointer address to Java objects - Designed to stay as close as possible to object-oriented design principles - Internal classes used by the entry points are kept in `D3D12::Internal` namespace and stored in `(...)/native-prism-d3d12/internal` - Contains `RenderingContext` class which imitates old API behavior - brings abstraction level closer to D3D12 API - `RenderingContext` prepares payloads and executes them on the `RenderThread` - Also contains other common mechanisms and classes that are shared across the backend - `Matrix`, `JNIBuffer`, `JNIString` etc - RenderThread implementation kept in `D3D12::RenderThread` namespace and stored in `(...)/native-prism-d3d12/render-thread` - Preparation of GPU workloads and recording D3D12 Command Lists takes a lot of CPU time, which causes low performance on machines with stronger dGPUs - dGPU will be done with its workload way faster than CPU can prepare the next one. `RenderThread` offloads this work to a separate CPU thread which allows to improve (and in some cases surpass - YMMV) D3D9 performance - Contains classes used inside the `RenderThread` to low-level manage D3D12 resources and data needed for rendering - Shader implementation kept in `D3D12::Shaders` namespace and stored in `(...)/native-prism-d3d12/shaders` - Contains abstract `Shader` class and implementations depending on what type of Shader the backend works with - Integrates with C++ headers generated by JSLC on build time to know what Shaders to expect and what resources to bind for them - Four types of Shaders supported so far: - `NativeShader` - integrates with Java-side `D3D12Shader` class to provide Prism/Decora shader support - `InternalShader` - integrates with internal backend shaders (ex. Passthrough, Phong) kept in `hlsl6` directory - `BlitPixelShader` - simple Pixel shader used to provide Blit functionality (not provided by D3D12 API) - `MipmapGenComputeShader` - Compute shader used for texture mipmap generation (not provided by D3D12 API) ### RenderPerfTest changes - Added new test cases which check for some edge cases missed earlier - `Label` and `RandomSizeText` - Added support for running multiple tests in one launch - Improved test result and error reporting ## Testing Testing was done on different Windows hardware - some laptops with weaker integrated GPUs, one PC with dedicated NVidia GPU unit + community testing done during EA phase. All testing done on latest available Windows 11 26H2 version. - Functional testing: - All headful tests pass on D3D12 pipeline in both Release and Debug - Verified samples: Ensemble and Toys - Performance testing: - Tested with `RenderPerfTest` - On iGPU machines all tests match/surpass D3D9 backend. - On dGPU machine (7950X, 4080S) many tests match/surpass D3D9 backend, but some are within the 80-85% range. Those will be addressed later on and are now tracked by [JDK-8388012](https://bugs.openjdk.org/browse/JDK-8388012). - Tested with recent update to `3DLighting`: - On iGPU, with 5000 meshes and 3 point lights - performance is ~114% of D3D9 (240FPS on 12 vs 210FPS on 9 with current master) ## Properties D3D12 backend can be configured and tested using some known and new Java properties: - `prism.verbose` - Adds verbose logging - `prism.debug` - Adds debug logging, requires build with `-PCONF=DebugNative` - `prism.d3d12.dred` - Adds D3D12 DRED breadcrumbs for debugging device crashes - `prism.d3d12.colorLogs` - Pretty-colors logs on console depending on severity - `prism.d3d12.fileLog` - Adds log output to a new file in current working directory Below properties require debug logging to be enabled (`prism.debug` property + build in `DebugNative`): - `prism.d3d12.trace` - Adds memory allocation/free trace logging - `prism.d3d12.printShaderLoad` - Adds information on Shader resources when Shaders are loaded - `prism.d3d12.debugLayers` - Enables Debug Validation Layers from D3D12 SDK, which will run extra API conformity checks. - `prism.d3d12.gpuDebug` - Enables GPU debugging from D3D12 SDK, which will run additional on-GPU checks at a major performance cost. Requires `prism.d3d12.debugLayers`. - `prism.d3d12.breakOnError` - Enables triggering a debug assertion upon Debug Layer errors. Requires `prism.d3d12.debugLayers`. ## Final notes to reviewers - To test this pipeline you *MUST* provide `-Dprism.order=d3d12` - There is no Glass or higher-level changes other than necessary one-line additions (ex. support for new Shader Model version in Decora). However, it is recommended to also test these changes with D3D9. - Known issues are tagged in JBS with `javafx-d3d12` tag and can be found here: https://bugs.openjdk.org/issues/?filter=51118 --------- - [x] I confirm that I make this contribution in accordance with the [OpenJDK Interim AI Policy](https://openjdk.org/legal/ai). ------------- Commit messages: - Implement Direct3D12 Rendering Pipeline Changes: https://git.openjdk.org/jfx/pull/2346/files Webrev: https://webrevs.openjdk.org/?repo=jfx&pr=2346&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8394770 Stats: 25167 lines in 155 files changed: 25048 ins; 6 del; 113 mod Patch: https://git.openjdk.org/jfx/pull/2346.diff Fetch: git fetch https://git.openjdk.org/jfx.git pull/2346/head:pull/2346 PR: https://git.openjdk.org/jfx/pull/2346
