Hook CAMetalLayer nextDrawable message

PR Feedback.
Replace the brittle callstack string comparison
This commit is contained in:
Jake Turner
2022-05-14 07:22:52 +01:00
committed by Baldur Karlsson
parent cef722a3d8
commit 00fdb79d68
3 changed files with 34 additions and 25 deletions
+30 -8
View File
@@ -46,12 +46,38 @@ WrappedMTLDevice::WrappedMTLDevice(MTL::Device *realMTLDevice, ResourceId objId)
WrappedMTLDevice *WrappedMTLDevice::MTLCreateSystemDefaultDevice(MTL::Device *realMTLDevice)
{
MTLFixupForMetalDriverAssert();
MTLHookObjcMethods();
ResourceId objId = ResourceIDGen::GetNewUniqueID();
WrappedMTLDevice *wrappedMTLDevice = new WrappedMTLDevice(realMTLDevice, objId);
return wrappedMTLDevice;
}
IMP WrappedMTLDevice::real_CAMetalLayer_nextDrawable;
uint64_t WrappedMTLDevice::nextDrawableTLSSlot;
MTL::Drawable *hooked_CAMetalLayer_nextDrawable(id self, SEL _cmd)
{
RDCASSERTEQUAL(Threading::GetTLSValue(WrappedMTLDevice::nextDrawableTLSSlot), 0);
Threading::SetTLSValue(WrappedMTLDevice::nextDrawableTLSSlot, (void *)(uintptr_t) true);
MTL::Drawable *drawable =
((MTL::Drawable * (*)(id, SEL))WrappedMTLDevice::real_CAMetalLayer_nextDrawable)(self, _cmd);
Threading::SetTLSValue(WrappedMTLDevice::nextDrawableTLSSlot, (void *)(uintptr_t) false);
return drawable;
}
void WrappedMTLDevice::MTLHookObjcMethods()
{
static bool s_hookObjcMethods = false;
if(s_hookObjcMethods)
return;
Method m =
class_getInstanceMethod(objc_lookUpClass("CAMetalLayer"), sel_registerName("nextDrawable"));
real_CAMetalLayer_nextDrawable = method_setImplementation(m, (IMP)hooked_CAMetalLayer_nextDrawable);
nextDrawableTLSSlot = Threading::AllocateTLSSlot();
}
void WrappedMTLDevice::MTLFixupForMetalDriverAssert()
{
static bool s_fixupMetalDriverAssert = false;
@@ -311,14 +337,10 @@ WrappedMTLTexture *WrappedMTLDevice::newTextureWithDescriptor(MTL::TextureDescri
IOSurfaceRef iosurface,
NS::UInteger plane)
{
return Common_NewTexture(descriptor, MetalChunk::MTLDevice_newTextureWithDescriptor_iosurface,
true, iosurface, plane);
}
WrappedMTLTexture *WrappedMTLDevice::nextDrawableTexture(MTL::TextureDescriptor *descriptor,
IOSurfaceRef iosurface, NS::UInteger plane)
{
return Common_NewTexture(descriptor, MetalChunk::MTLDevice_newTextureWithDescriptor_nextDrawable,
bool nextDrawable = (bool)(uintptr_t)Threading::GetTLSValue(nextDrawableTLSSlot);
return Common_NewTexture(descriptor,
nextDrawable ? MetalChunk::MTLDevice_newTextureWithDescriptor_nextDrawable
: MetalChunk::MTLDevice_newTextureWithDescriptor_iosurface,
true, iosurface, plane);
}
+4 -2
View File
@@ -51,8 +51,6 @@ public:
NS::Error **error);
WrappedMTLTexture *newTextureWithDescriptor(MTL::TextureDescriptor *descriptor,
IOSurfaceRef iosurface, NS::UInteger plane);
WrappedMTLTexture *nextDrawableTexture(MTL::TextureDescriptor *descriptor, IOSurfaceRef iosurface,
NS::UInteger plane);
WrappedMTLTexture *newTextureWithDescriptor(MTL::TextureDescriptor *descriptor);
template <typename SerialiserType>
bool Serialise_newTextureWithDescriptor(SerialiserType &ser, WrappedMTLTexture *,
@@ -96,8 +94,12 @@ public:
TypeEnum = eResDevice
};
static uint64_t nextDrawableTLSSlot;
static IMP real_CAMetalLayer_nextDrawable;
private:
static void MTLFixupForMetalDriverAssert();
static void MTLHookObjcMethods();
bool Prepare_InitialState(WrappedMTLObject *res);
uint64_t GetSize_InitialState(ResourceId id, const MetalInitialContents &initial);
template <typename SerialiserType>
@@ -266,21 +266,6 @@
plane:(NSUInteger)plane
API_AVAILABLE(macos(10.11), ios(11.0))
{
NS::String *nsString = (NS::String *)[[NSThread callStackSymbols] objectAtIndex:1];
// Example parentCallsite string
//"1 QuartzCore 0x00000001b956ece8 _ZL19get_unused_drawableP20_CAMetalLayerPrivatebb + 676"
bool nextDrawable = false;
if(nsString)
{
rdcstr parentCallsite(nsString->utf8String());
nextDrawable = (parentCallsite.contains("CAMetalLayer") && parentCallsite.contains("drawable"));
}
if(nextDrawable)
{
return id<MTLTexture>(GetWrapped(self)->nextDrawableTexture(
(MTL::TextureDescriptor *)descriptor, iosurface, plane));
}
return id<MTLTexture>(GetWrapped(self)->newTextureWithDescriptor(
(MTL::TextureDescriptor *)descriptor, iosurface, plane));
}