Skip to content

Commit

Permalink
Move metal drawable management to ObjC
Browse files Browse the repository at this point in the history
  • Loading branch information
elijah-semyonov committed Jun 7, 2024
1 parent 4601d2c commit 39d436a
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
EA70A7EC2B27106100300068 /* CMPAccessibilityContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = EA70A7E92B27106100300068 /* CMPAccessibilityContainer.m */; };
EA82F4F92B86144E00465418 /* CMPOSLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = EA82F4F82B86144E00465418 /* CMPOSLogger.m */; };
EA82F4FC2B86184F00465418 /* CMPOSLoggerInterval.m in Sources */ = {isa = PBXBuildFile; fileRef = EA82F4FB2B86184F00465418 /* CMPOSLoggerInterval.m */; };
EAB33E182C12E746002CFF44 /* CMPMetalDrawablesHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = EAB33E172C12E746002CFF44 /* CMPMetalDrawablesHandler.m */; };
EABD912B2BC02B5F00455279 /* CMPInteropWrappingView.m in Sources */ = {isa = PBXBuildFile; fileRef = EABD912A2BC02B5F00455279 /* CMPInteropWrappingView.m */; };
EAC703E32B8C826E001ECDA6 /* CMPAccessibilityElement.m in Sources */ = {isa = PBXBuildFile; fileRef = EA70A7E82B27106100300068 /* CMPAccessibilityElement.m */; };
EAC703E42B8C826E001ECDA6 /* CMPViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 997DFCDD2B18D135000B56B5 /* CMPViewController.m */; };
Expand Down Expand Up @@ -82,6 +83,8 @@
EA82F4F82B86144E00465418 /* CMPOSLogger.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CMPOSLogger.m; sourceTree = "<group>"; };
EA82F4FA2B86184F00465418 /* CMPOSLoggerInterval.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CMPOSLoggerInterval.h; sourceTree = "<group>"; };
EA82F4FB2B86184F00465418 /* CMPOSLoggerInterval.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CMPOSLoggerInterval.m; sourceTree = "<group>"; };
EAB33E162C12E746002CFF44 /* CMPMetalDrawablesHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CMPMetalDrawablesHandler.h; sourceTree = "<group>"; };
EAB33E172C12E746002CFF44 /* CMPMetalDrawablesHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CMPMetalDrawablesHandler.m; sourceTree = "<group>"; };
EABD91292BC02B5F00455279 /* CMPInteropWrappingView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CMPInteropWrappingView.h; sourceTree = "<group>"; };
EABD912A2BC02B5F00455279 /* CMPInteropWrappingView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CMPInteropWrappingView.m; sourceTree = "<group>"; };
EAC703DF2B8C8154001ECDA6 /* CMPUIKitUtilsTestApp-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CMPUIKitUtilsTestApp-Bridging-Header.h"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -134,6 +137,8 @@
99DCAB0D2BD00F5C002E6AC7 /* CMPTextLoupeSession.m */,
99D97A862BF73A9B0035552B /* CMPEditMenuView.h */,
99D97A872BF73A9B0035552B /* CMPEditMenuView.m */,
EAB33E162C12E746002CFF44 /* CMPMetalDrawablesHandler.h */,
EAB33E172C12E746002CFF44 /* CMPMetalDrawablesHandler.m */,
);
path = CMPUIKitUtils;
sourceTree = "<group>";
Expand Down Expand Up @@ -308,6 +313,7 @@
buildActionMask = 2147483647;
files = (
997DFCDE2B18D135000B56B5 /* CMPViewController.m in Sources */,
EAB33E182C12E746002CFF44 /* CMPMetalDrawablesHandler.m in Sources */,
99D97A882BF73A9B0035552B /* CMPEditMenuView.m in Sources */,
EABD912B2BC02B5F00455279 /* CMPInteropWrappingView.m in Sources */,
EA70A7EC2B27106100300068 /* CMPAccessibilityContainer.m in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,12 @@

#define CMP_MUST_BE_OVERRIDED
#define CMP_MUST_BE_OVERRIDED_INVARIANT_VIOLATION assert(false && "MUST_OVERRIDE");

// Marker for indicating that raw pointer returned from a function is owned by the caller
#define CMP_OWNED

// Marker for indicating that raw pointer is consumed when passed as an argument
#define CMP_CONSUMED

// Marker for indicating that raw pointer is implied as borrowed when returned from a function or passed as an argument
#define CMP_BORROWED
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//
// CMPMetalDrawablesHandler.h
// CMPUIKitUtils
//
// Created by Ilia.Semenov on 07/06/2024.
//

#import <Foundation/Foundation.h>
#import <QuartzCore/QuartzCore.h>
#import <Metal/Metal.h>

#import "CMPMacros.h"

NS_ASSUME_NONNULL_BEGIN

@interface CMPMetalDrawablesHandler : NSObject

- (instancetype)initWithMetalLayer:(CAMetalLayer *)metalLayer;

- (void * __nullable CMP_OWNED)nextDrawable;
- (void)releaseDrawable:(void * CMP_CONSUMED)drawablePtr;
- (void * CMP_BORROWED)drawableTexture:(void * CMP_BORROWED)drawablePtr;
- (void)presentDrawable:(void * CMP_CONSUMED)drawablePtr;
- (void)scheduleDrawablePresentation:(void * CMP_CONSUMED)drawablePtr onCommandBuffer:(id <MTLCommandBuffer>)commandBuffer;


@end

NS_ASSUME_NONNULL_END
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//
// CMPMetalDrawablesHandler.m
// CMPUIKitUtils
//
// Created by Ilia.Semenov on 07/06/2024.
//

#import "CMPMetalDrawablesHandler.h"

@implementation CMPMetalDrawablesHandler {
CAMetalLayer *_metalLayer;
}

- (instancetype)initWithMetalLayer:(CAMetalLayer *)metalLayer {
self = [super init];
if (self) {
_metalLayer = metalLayer;
}
return self;
}

- (void * __nullable CMP_OWNED)nextDrawable {
id <CAMetalDrawable> drawable = [_metalLayer nextDrawable];

if (drawable) {
void *ptr = (__bridge_retained void *)drawable;
return ptr;
} else {
return NULL;
}
}

- (void)releaseDrawable:(void * CMP_CONSUMED)drawablePtr {
assert(drawablePtr != NULL);

id <CAMetalDrawable> drawable __unused = (__bridge_transfer id <CAMetalDrawable>)drawablePtr;
// drawable will be released by ARC
}

- (void * CMP_BORROWED)drawableTexture:(void * CMP_BORROWED)drawablePtr {
assert(drawablePtr != NULL);

id <CAMetalDrawable> drawable = (__bridge id <CAMetalDrawable>)drawablePtr;
id <MTLTexture> texture = drawable.texture;
void *texturePtr = (__bridge void *)texture;
return texturePtr;
}

- (void)presentDrawable:(void * CMP_CONSUMED)drawablePtr {
assert(drawablePtr != NULL);

id <CAMetalDrawable> drawable __unused = (__bridge_transfer id <CAMetalDrawable>)drawablePtr;
[drawable present];
}

- (void)scheduleDrawablePresentation:(void * CMP_CONSUMED)drawablePtr onCommandBuffer:(id <MTLCommandBuffer>)commandBuffer {
assert(drawablePtr != NULL);

id <CAMetalDrawable> drawable __unused = (__bridge_transfer id <CAMetalDrawable>)drawablePtr;
[commandBuffer presentDrawable:drawable];
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ FOUNDATION_EXPORT const unsigned char CMPUIKitUtilsVersionString[];
#import "CMPAccessibilityContainer.h"
#import "CMPOSLogger.h"
#import "CMPTextLoupeSession.h"
#import "CMPMetalDrawablesHandler.h"
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import androidx.compose.ui.interop.UIKitInteropState
import androidx.compose.ui.interop.UIKitInteropTransaction
import androidx.compose.ui.interop.doLocked
import androidx.compose.ui.interop.isNotEmpty
import androidx.compose.ui.uikit.utils.CMPMetalDrawablesHandler
import androidx.compose.ui.util.fastForEach
import androidx.compose.ui.util.trace
import kotlin.math.roundToInt
Expand Down Expand Up @@ -145,6 +146,7 @@ internal class MetalRedrawer(
private val metalLayer: CAMetalLayer,
private val callbacks: MetalRedrawerCallbacks
) {
private val metalDrawableHandler = CMPMetalDrawablesHandler(metalLayer)
// Workaround for KN compiler bug
// Type mismatch: inferred type is objcnames.protocols.MTLDeviceProtocol but platform.Metal.MTLDeviceProtocol was expected
@Suppress("USELESS_CAST")
Expand Down Expand Up @@ -316,7 +318,7 @@ internal class MetalRedrawer(
}

val metalDrawable = trace("MetalRedrawer:draw:nextDrawable") {
metalLayer.nextDrawable()
metalDrawableHandler.nextDrawable()
}

if (metalDrawable == null) {
Expand All @@ -328,7 +330,7 @@ internal class MetalRedrawer(
}

val renderTarget =
BackendRenderTarget.makeMetal(width, height, metalDrawable.texture.objcPtr())
BackendRenderTarget.makeMetal(width, height, metalDrawableHandler.drawableTexture(metalDrawable).rawValue)

val surface = Surface.makeFromBackendRenderTarget(
context,
Expand All @@ -344,6 +346,7 @@ internal class MetalRedrawer(
// Logger.warn { "'Surface.makeFromBackendRenderTarget' returned null. Skipping the frame." }
picture.close()
renderTarget.close()
metalDrawableHandler.releaseDrawable(metalDrawable)
dispatch_semaphore_signal(inflightSemaphore)
return@autoreleasepool
}
Expand Down Expand Up @@ -372,7 +375,9 @@ internal class MetalRedrawer(
commandBuffer.label = "Present"

if (!presentsWithTransaction) {
commandBuffer.presentDrawable(metalDrawable)
// scheduleDrawablePresentation consumes metalDrawable
// don't use metalDrawable after this call
metalDrawableHandler.scheduleDrawablePresentation(metalDrawable, commandBuffer)
}

commandBuffer.addCompletedHandler {
Expand All @@ -388,7 +393,9 @@ internal class MetalRedrawer(
commandBuffer.waitUntilScheduled()
}

metalDrawable.present()
// presentDrawable consumes metalDrawable
// don't use metalDrawable after this call
metalDrawableHandler.presentDrawable(metalDrawable)

interopTransaction.actions.fastForEach {
it.invoke()
Expand Down

0 comments on commit 39d436a

Please sign in to comment.