RFR: 8271024: Implement macOS Metal Rendering Pipeline [v6]

Lukasz Kostyra lkostyra at openjdk.org
Tue Jul 8 12:06:53 UTC 2025


On Wed, 2 Jul 2025 07:53:24 GMT, Ambarish Rapte <arapte at openjdk.org> wrote:

>> ### Description
>> This is the implementation of new graphics rendering pipeline for JavaFX using Metal APIs on MacOS.
>> We released two Early Access (EA) builds and have reached a stage where it is ready to be integrated.
>> Default rendering pipeline on macOS has not been changed by this PR. OpenGL still stays as the default rendering pipeline and Metal rendering pipeline is optional to choose (by providing  `-Dprism.order=mtl`)
>> The `-Dprism.verbose=true` option can be used to verify the rendering pipeline in use.
>> 
>> ### Details about the changes
>> 
>> **Shader changes**
>> - MSLBackend class: This is the primary class that parses (Prism and Decora) jsl shaders into Metal shaders(msl)
>> - There are a few additional Metal shader files added under directory : modules/javafx.graphics/src/main/native-prism-mtl/msl
>> 
>> **Build changes** - There are new tasks added to build.gradle for
>> - Generation/ Compilation/ linking of Metal shaders
>> - Compilation of Prism Java and Objective C files
>> 
>> **Prism** - Prism is the rendering engine of JavaFX.
>> - Added Metal specific Java classes and respective native implementation which use Metal APIs
>> - Java side changes:
>>   - New Metal specific classes: Classes prefixed with MTL, are added here : modules/javafx.graphics/src/main/java/com/sun/prism/mtl 
>>   - Modification to Prism common classes: A few limited changes were required in Prism common classes to support Metal classes. 
>> - Native side changes:
>>   - New Metal specific Objective C implementation is added here: modules/javafx.graphics/src/main/native-prism-mtl
>> 
>> **Glass** - Glass is the windowing toolkit of JavaFX
>> - Existing Glass classes are refactored to support both OpenGL and Metal pipelines
>> - Added Metal specific Glass implementation.
>> 
>> ### Testing
>> - Testing performed on different hardware and macOS versions.
>>   - HW - macBooks with Intel, Intel with discrete graphics card, Apple Silicon (M1, M2 and M4)
>>   - macOS versions - macOS 13, macOS 14 and macOS 15
>> - Functional Testing:
>>   - All headful tests pass with Metal pipeline.
>>   - Verified samples applications: Ensemble and toys
>> - Performance Testing:
>>   - Tested with RenderPerfTest: Almost all tests match/exceed es2 performance except a few that fall a little short on different hardwares. These will be addressed separately (there are open bugs already filed)
>> 
>> ### Note to reviewers :
>> - Providing `-Dprism.order=mtl` option is a must for testing the Metal pipeline
>> - It woul...
>
> Ambarish Rapte has updated the pull request incrementally with one additional commit since the last revision:
> 
>   add @Override

Good work!

Reviewed the Metal-native-side of this commit (`native-prism-mtl` folder) and left some comments to talk through, nothing extremely major though. I'll verify the code on my side once we get closer to review completion.

modules/javafx.graphics/src/main/native-prism-mtl/MetalContext.m line 1437:

> 1435:     [pCtx endCurrentRenderEncoder];
> 1436: 
> 1437:     id<MTLCommandBuffer> commandBuffer = [pCtx getCurrentCommandBuffer];

I think most of this function should become a `MetalContext` method that would be called here. That way we separate the Metal-related implementation from JNI entry points and it follows the pattern of other JNI entry points in this file.

modules/javafx.graphics/src/main/native-prism-mtl/MetalShader.m line 167:

> 165:         pipeState = [[context getPipelineManager] getPipeStateWithFragFunc:fragmentFunction
> 166:                                                              compositeMode:compositeMode];
> 167:         [psDict setObject:pipeState forKey:keyCompMode];

I am not 100% sure why there is a need to duplicate PipelineState dictionaries here and to create a Shader-specific cache of States. If you need to get a PipelineState, why not always directly call on `MetalPipelineManager`?

modules/javafx.graphics/src/main/native-prism-mtl/MetalTexture.m line 235:

> 233:     id<MTLCommandBuffer> commandBuffer = [context getCurrentCommandBuffer];
> 234:     @autoreleasepool {
> 235:         id<MTLBlitCommandEncoder> blitEncoder = [commandBuffer blitCommandEncoder];

Similarly to `MetalContext` comment, I think we should separate JNI entry point code and argument parsing/converting from actual Metal-reaching implementation. I would also move this to a `MetalTexture` method.

modules/javafx.graphics/src/main/native-prism-mtl/MetalTexture.m line 300:

> 298: 
> 299:     @autoreleasepool {
> 300:         id<MTLBlitCommandEncoder> blitEncoder = [commandBuffer blitCommandEncoder];

As above

modules/javafx.graphics/src/main/native-prism-mtl/MetalTexture.m line 364:

> 362: 
> 363:     @autoreleasepool {
> 364:         id<MTLBlitCommandEncoder> blitEncoder = [commandBuffer blitCommandEncoder];

As above

modules/javafx.graphics/src/main/native-prism-mtl/MetalTexture.m line 407:

> 405: 
> 406:     @autoreleasepool {
> 407:         id<MTLDevice> device = [context getDevice];

As above

-------------

PR Review: https://git.openjdk.org/jfx/pull/1824#pullrequestreview-2961851748
PR Review Comment: https://git.openjdk.org/jfx/pull/1824#discussion_r2192155071
PR Review Comment: https://git.openjdk.org/jfx/pull/1824#discussion_r2192281270
PR Review Comment: https://git.openjdk.org/jfx/pull/1824#discussion_r2192317134
PR Review Comment: https://git.openjdk.org/jfx/pull/1824#discussion_r2192305858
PR Review Comment: https://git.openjdk.org/jfx/pull/1824#discussion_r2192306212
PR Review Comment: https://git.openjdk.org/jfx/pull/1824#discussion_r2192307217


More information about the openjfx-dev mailing list