diff --git a/renderdoc/driver/metal/CMakeLists.txt b/renderdoc/driver/metal/CMakeLists.txt index cd96aca3c..2a5dd4e4f 100644 --- a/renderdoc/driver/metal/CMakeLists.txt +++ b/renderdoc/driver/metal/CMakeLists.txt @@ -20,6 +20,9 @@ set(sources metal_function.h metal_function_bridge.mm metal_common.h + metal_command_queue.cpp + metal_command_queue.h + metal_command_queue_bridge.mm metal_core.cpp metal_core.h metal_manager.cpp diff --git a/renderdoc/driver/metal/metal_command_queue.cpp b/renderdoc/driver/metal/metal_command_queue.cpp new file mode 100644 index 000000000..78ab7e5ea --- /dev/null +++ b/renderdoc/driver/metal/metal_command_queue.cpp @@ -0,0 +1,33 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2022 Baldur Karlsson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#include "metal_command_queue.h" +#include "metal_device.h" + +WrappedMTLCommandQueue::WrappedMTLCommandQueue(MTL::CommandQueue *realMTLCommandQueue, + ResourceId objId, WrappedMTLDevice *wrappedMTLDevice) + : WrappedMTLObject(realMTLCommandQueue, objId, wrappedMTLDevice, wrappedMTLDevice->GetStateRef()) +{ + objcBridge = AllocateObjCBridge(this); +} diff --git a/renderdoc/driver/metal/metal_command_queue.h b/renderdoc/driver/metal/metal_command_queue.h new file mode 100644 index 000000000..2841dee20 --- /dev/null +++ b/renderdoc/driver/metal/metal_command_queue.h @@ -0,0 +1,42 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2022 Baldur Karlsson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#pragma once + +#include "metal_common.h" + +class WrappedMTLCommandQueue : public WrappedMTLObject +{ +public: + WrappedMTLCommandQueue(MTL::CommandQueue *realMTLCommandQueue, ResourceId objId, + WrappedMTLDevice *wrappedMTLDevice); + + MTL::CommandQueue *GetReal() { return (MTL::CommandQueue *)real; } + enum + { + TypeEnum = eResCommandQueue + }; + +private: +}; diff --git a/renderdoc/driver/metal/metal_command_queue_bridge.mm b/renderdoc/driver/metal/metal_command_queue_bridge.mm new file mode 100644 index 000000000..11a104ac1 --- /dev/null +++ b/renderdoc/driver/metal/metal_command_queue_bridge.mm @@ -0,0 +1,103 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2022 Baldur Karlsson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#include "metal_command_queue.h" +#include "metal_types_bridge.h" + +// Bridge for MTLCommandQueue +@implementation ObjCBridgeMTLCommandQueue + +// ObjCBridgeMTLCommandQueue specific +- (id)real +{ + MTL::CommandQueue *real = self.wrappedCPP->GetReal(); + return id(real); +} + +// Use the real MTLCommandQueue to find methods from messages +- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector +{ + id fwd = self.real; + return [fwd methodSignatureForSelector:aSelector]; +} + +// Forward any unknown messages to the real MTLCommandQueue +- (void)forwardInvocation:(NSInvocation *)invocation +{ + SEL aSelector = [invocation selector]; + + if([self.real respondsToSelector:aSelector]) + [invocation invokeWithTarget:self.real]; + else + [super forwardInvocation:invocation]; +} + +// MTLCommandQueue : based on the protocol defined in +// Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Metal.framework/Headers/MTLCommandQueue.h + +- (nullable NSString *)label +{ + return self.real.label; +} + +- (void)setLabel:value +{ + self.real.label = value; +} + +- (id)device +{ + return id(self.wrappedCPP->GetObjCBridgeMTLDevice()); +} + +- (nullable id)commandBuffer +{ + METAL_NOT_HOOKED(); + return [self.real commandBuffer]; +} + +- (nullable id)commandBufferWithDescriptor:(MTLCommandBufferDescriptor *)descriptor + API_AVAILABLE(macos(11.0), ios(14.0)) +{ + METAL_NOT_HOOKED(); + return [self.real commandBufferWithDescriptor:descriptor]; +} + +- (nullable id)commandBufferWithUnretainedReferences +{ + METAL_NOT_HOOKED(); + return [self.real commandBufferWithUnretainedReferences]; +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-implementations" +- (void)insertDebugCaptureBoundary + API_DEPRECATED("Use MTLCaptureScope instead", macos(10.11, 10.13), ios(8.0, 11.0)) +{ + METAL_NOT_HOOKED(); + return [self.real insertDebugCaptureBoundary]; +} +#pragma clang diagnostic pop + +@end diff --git a/renderdoc/driver/metal/metal_common.h b/renderdoc/driver/metal/metal_common.h index 9f0a53e46..1ff13c82a 100644 --- a/renderdoc/driver/metal/metal_common.h +++ b/renderdoc/driver/metal/metal_common.h @@ -35,6 +35,7 @@ enum class MetalChunk : uint32_t { MTLCreateSystemDefaultDevice = (uint32_t)SystemChunk::FirstDriverChunk, + MTLDevice_newCommandQueue, MTLDevice_newDefaultLibrary, MTLDevice_newLibraryWithSource, MTLLibrary_newFunctionWithName, @@ -59,9 +60,18 @@ DECLARE_REFLECTION_ENUM(MetalChunk); template \ bool CONCAT(Serialise_, func(SerialiserType &ser, ##__VA_ARGS__)); -#define INSTANTIATE_FUNCTION_SERIALISED(CLASS, ret, func, ...) \ - template bool CLASS::CONCAT(Serialise_, func(ReadSerialiser &ser, __VA_ARGS__)); \ - template bool CLASS::CONCAT(Serialise_, func(WriteSerialiser &ser, __VA_ARGS__)); +#define INSTANTIATE_FUNCTION_SERIALISED(CLASS, ret, func, ...) \ + template bool CLASS::CONCAT(Serialise_, func(ReadSerialiser &ser, ##__VA_ARGS__)); \ + template bool CLASS::CONCAT(Serialise_, func(WriteSerialiser &ser, ##__VA_ARGS__)); + +#define DECLARE_FUNCTION_WITH_RETURN_SERIALISED(ret, func, ...) \ + ret func(__VA_ARGS__); \ + template \ + bool CONCAT(Serialise_, func(SerialiserType &ser, ret, ##__VA_ARGS__)); + +#define INSTANTIATE_FUNCTION_WITH_RETURN_SERIALISED(CLASS, ret, func, ...) \ + template bool CLASS::CONCAT(Serialise_, func(ReadSerialiser &ser, ret, ##__VA_ARGS__)); \ + template bool CLASS::CONCAT(Serialise_, func(WriteSerialiser &ser, ret, ##__VA_ARGS__)); // A handy macro to say "is the serialiser reading and we're doing replay-mode stuff?" // The reason we check both is that checking the first allows the compiler to eliminate the other diff --git a/renderdoc/driver/metal/metal_device.cpp b/renderdoc/driver/metal/metal_device.cpp index 4b7fcb485..91c6e3b4f 100644 --- a/renderdoc/driver/metal/metal_device.cpp +++ b/renderdoc/driver/metal/metal_device.cpp @@ -23,6 +23,7 @@ ******************************************************************************/ #include "metal_device.h" +#include "metal_command_queue.h" #include "metal_helpers_bridge.h" #include "metal_library.h" #include "metal_manager.h" @@ -47,6 +48,46 @@ WrappedMTLDevice *WrappedMTLDevice::MTLCreateSystemDefaultDevice(MTL::Device *re return wrappedMTLDevice; } +template +bool WrappedMTLDevice::Serialise_newCommandQueue(SerialiserType &ser, WrappedMTLCommandQueue *queue) +{ + SERIALISE_ELEMENT_LOCAL(CommandQueue, GetResID(queue)).TypedAs("MTLCommandQueue"_lit); + + SERIALISE_CHECK_READ_ERRORS(); + + if(IsReplayingAndReading()) + { + // TODO: implement RD MTL replay + } + return true; +} + +WrappedMTLCommandQueue *WrappedMTLDevice::newCommandQueue() +{ + MTL::CommandQueue *realMTLCommandQueue; + SERIALISE_TIME_CALL(realMTLCommandQueue = GetReal()->newCommandQueue()); + WrappedMTLCommandQueue *wrappedMTLCommandQueue; + ResourceId id = GetResourceManager()->WrapResource(realMTLCommandQueue, wrappedMTLCommandQueue); + if(IsCaptureMode(m_State)) + { + Chunk *chunk = NULL; + { + CACHE_THREAD_SERIALISER(); + SCOPED_SERIALISE_CHUNK(MetalChunk::MTLDevice_newCommandQueue); + Serialise_newCommandQueue(ser, wrappedMTLCommandQueue); + chunk = scope.Get(); + } + MetalResourceRecord *record = GetResourceManager()->AddResourceRecord(wrappedMTLCommandQueue); + record->AddChunk(chunk); + } + else + { + // TODO: implement RD MTL replay + // GetResourceManager()->AddLiveResource(id, wrappedMTLCommandQueue); + } + return wrappedMTLCommandQueue; +} + template bool WrappedMTLDevice::Serialise_newDefaultLibrary(SerialiserType &ser, WrappedMTLLibrary *library) { @@ -143,6 +184,9 @@ WrappedMTLLibrary *WrappedMTLDevice::newLibraryWithSource(NS::String *source, return wrappedMTLLibrary; } +INSTANTIATE_FUNCTION_WITH_RETURN_SERIALISED(WrappedMTLDevice, WrappedMTLCommandQueue *, + newCommandQueue); + template bool WrappedMTLDevice::Serialise_newDefaultLibrary(ReadSerialiser &ser, WrappedMTLLibrary *library); template bool WrappedMTLDevice::Serialise_newDefaultLibrary(WriteSerialiser &ser, diff --git a/renderdoc/driver/metal/metal_device.h b/renderdoc/driver/metal/metal_device.h index 450747298..38897b1e8 100644 --- a/renderdoc/driver/metal/metal_device.h +++ b/renderdoc/driver/metal/metal_device.h @@ -37,6 +37,8 @@ public: MTL::Device *GetReal() { return (MTL::Device *)real; } static WrappedMTLDevice *MTLCreateSystemDefaultDevice(MTL::Device *realMTLDevice); + DECLARE_FUNCTION_WITH_RETURN_SERIALISED(WrappedMTLCommandQueue *, newCommandQueue); + WrappedMTLLibrary *newDefaultLibrary(); template bool Serialise_newDefaultLibrary(SerialiserType &ser, WrappedMTLLibrary *library); diff --git a/renderdoc/driver/metal/metal_device_bridge.mm b/renderdoc/driver/metal/metal_device_bridge.mm index 0445b0988..98f9a1e96 100644 --- a/renderdoc/driver/metal/metal_device_bridge.mm +++ b/renderdoc/driver/metal/metal_device_bridge.mm @@ -24,6 +24,7 @@ #include "metal_device.h" #include +#include "metal_command_queue.h" #include "metal_library.h" #include "metal_types_bridge.h" @@ -182,8 +183,9 @@ - (nullable id)newCommandQueue { - METAL_NOT_HOOKED(); - return [self.real newCommandQueue]; + WrappedMTLCommandQueue *wrapped = self.wrappedCPP->newCommandQueue(); + MTL::CommandQueue *objc = GetObjCBridge(wrapped); + return id(objc); } - (nullable id)newCommandQueueWithMaxCommandBufferCount:(NSUInteger)maxCommandBufferCount diff --git a/renderdoc/driver/metal/metal_resources.h b/renderdoc/driver/metal/metal_resources.h index 3c2c4deb7..4cdb68505 100644 --- a/renderdoc/driver/metal/metal_resources.h +++ b/renderdoc/driver/metal/metal_resources.h @@ -35,6 +35,7 @@ class MetalResourceManager; enum MetalResourceType { eResUnknown = 0, + eResCommandQueue, eResDevice, eResLibrary, eResFunction, diff --git a/renderdoc/driver/metal/metal_types.h b/renderdoc/driver/metal/metal_types.h index d15293415..b5746605f 100644 --- a/renderdoc/driver/metal/metal_types.h +++ b/renderdoc/driver/metal/metal_types.h @@ -29,6 +29,7 @@ #include "serialise/serialiser.h" #define METALCPP_WRAPPED_PROTOCOLS(FUNC) \ + FUNC(CommandQueue); \ FUNC(Device); \ FUNC(Function); \ FUNC(Library); diff --git a/renderdoc/driver/metal/metal_types_bridge.h b/renderdoc/driver/metal/metal_types_bridge.h index 3b1c5be8d..1963298e1 100644 --- a/renderdoc/driver/metal/metal_types_bridge.h +++ b/renderdoc/driver/metal/metal_types_bridge.h @@ -26,8 +26,7 @@ #include "metal_types.h" -#import -#import +#import // clang-format off #define DECLARE_OBJC_WRAPPED_INTERFACES(CPPTYPE) \ diff --git a/renderdoc/driver/metal/metal_types_bridge.mm b/renderdoc/driver/metal/metal_types_bridge.mm index 0f5e1b399..b91f9bff8 100644 --- a/renderdoc/driver/metal/metal_types_bridge.mm +++ b/renderdoc/driver/metal/metal_types_bridge.mm @@ -23,6 +23,7 @@ ******************************************************************************/ #include "metal_types_bridge.h" +#include "metal_command_queue.h" #include "metal_device.h" #include "metal_function.h" #include "metal_library.h"