From c7dae679c12a2f36b150b6f041e241b567c87ac5 Mon Sep 17 00:00:00 2001 From: Jake Turner Date: Fri, 1 Jul 2022 14:47:55 +0100 Subject: [PATCH] Use objc_constructInstance in AllocateObjCBridge This constructs in-place the ObjC bridge class. This fixes a bug where the reference count of the ObjC bridge class was not guaranteed to be initialized on construction. --- renderdoc/driver/metal/metal_types.cpp | 46 ++++++++++++++------------ 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/renderdoc/driver/metal/metal_types.cpp b/renderdoc/driver/metal/metal_types.cpp index 40640747e..0f5acc88a 100644 --- a/renderdoc/driver/metal/metal_types.cpp +++ b/renderdoc/driver/metal/metal_types.cpp @@ -40,27 +40,31 @@ RDCCOMPILE_ASSERT(sizeof(NS::Integer) == sizeof(std::intptr_t), "NS::Integer siz RDCCOMPILE_ASSERT(sizeof(NS::UInteger) == sizeof(std::uintptr_t), "NS::UInteger size does not match"); -#define DEFINE_OBJC_HELPERS(CPPTYPE) \ - void AllocateObjCBridge(WrappedMTL##CPPTYPE *wrappedCPP) \ - { \ - RDCCOMPILE_ASSERT((offsetof(WrappedMTL##CPPTYPE, m_ObjcBridge) == 0), \ - "m_ObjcBridge must be at offsetof 0"); \ - const char *const className = "ObjCBridgeMTL" #CPPTYPE; \ - static Class klass = objc_lookUpClass(className); \ - static size_t classSize = class_getInstanceSize(klass); \ - if(classSize != sizeof(wrappedCPP->m_ObjcBridge)) \ - { \ - RDCFATAL("'%s' classSize != sizeof(m_ObjcBridge) %lu != %lu", className, classSize, \ - sizeof(wrappedCPP->m_ObjcBridge)); \ - } \ - wrappedCPP->m_ObjcBridge = klass; \ - MTL::CPPTYPE *real = (MTL::CPPTYPE *)wrappedCPP->m_Real; \ - if(real) \ - { \ - id objc = (id)&wrappedCPP->m_ObjcBridge; \ - objc_setAssociatedObject((id)real, objc, objc, OBJC_ASSOCIATION_RETAIN); \ - ((MTL::CPPTYPE *)objc)->release(); \ - } \ +#define DEFINE_OBJC_HELPERS(CPPTYPE) \ + void AllocateObjCBridge(WrappedMTL##CPPTYPE *wrappedCPP) \ + { \ + RDCCOMPILE_ASSERT((offsetof(WrappedMTL##CPPTYPE, m_ObjcBridge) == 0), \ + "m_ObjcBridge must be at offsetof 0"); \ + const char *const className = "ObjCBridgeMTL" #CPPTYPE; \ + static Class klass = objc_lookUpClass(className); \ + static size_t classSize = class_getInstanceSize(klass); \ + if(classSize != sizeof(wrappedCPP->m_ObjcBridge)) \ + { \ + RDCFATAL("'%s' classSize != sizeof(m_ObjcBridge) %lu != %lu", className, classSize, \ + sizeof(wrappedCPP->m_ObjcBridge)); \ + } \ + id objc = objc_constructInstance(klass, &wrappedCPP->m_ObjcBridge); \ + if(objc != (id)&wrappedCPP->m_ObjcBridge) \ + { \ + RDCFATAL("'%s' objc != m_ObjcBridge %p != %p", className, objc, &wrappedCPP->m_ObjcBridge); \ + } \ + MTL::CPPTYPE *real = (MTL::CPPTYPE *)wrappedCPP->m_Real; \ + if(real) \ + { \ + objc_setAssociatedObject((id)real, objc, objc, OBJC_ASSOCIATION_RETAIN); \ + ((MTL::CPPTYPE *)objc)->release(); \ + } \ + } \ } METALCPP_WRAPPED_PROTOCOLS(DEFINE_OBJC_HELPERS)