Added wrapped MTLCommandQueue

Implemented capture serialisation for MTLDevice::newCommandQueue
Introduce new helper macros DECLARE_FUNCTION_WITH_RETURN_SERIALISED & INSTANTIATE_FUNCTION_WITH_RETURN_SERIALISED for serialising APIs with return values that need serialising ie. Metal resource creation APIs
This commit is contained in:
Jake Turner
2022-03-15 19:11:41 +00:00
committed by Baldur Karlsson
parent f01a4df484
commit 0c8e41b201
12 changed files with 248 additions and 7 deletions
+3
View File
@@ -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
@@ -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);
}
@@ -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:
};
@@ -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<MTLCommandQueue>)real
{
MTL::CommandQueue *real = self.wrappedCPP->GetReal();
return id<MTLCommandQueue>(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<MTLDevice>)device
{
return id<MTLDevice>(self.wrappedCPP->GetObjCBridgeMTLDevice());
}
- (nullable id<MTLCommandBuffer>)commandBuffer
{
METAL_NOT_HOOKED();
return [self.real commandBuffer];
}
- (nullable id<MTLCommandBuffer>)commandBufferWithDescriptor:(MTLCommandBufferDescriptor *)descriptor
API_AVAILABLE(macos(11.0), ios(14.0))
{
METAL_NOT_HOOKED();
return [self.real commandBufferWithDescriptor:descriptor];
}
- (nullable id<MTLCommandBuffer>)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
+13 -3
View File
@@ -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 <typename SerialiserType> \
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 <typename SerialiserType> \
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
+44
View File
@@ -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 <typename SerialiserType>
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 <typename SerialiserType>
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,
+2
View File
@@ -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 <typename SerialiserType>
bool Serialise_newDefaultLibrary(SerialiserType &ser, WrappedMTLLibrary *library);
@@ -24,6 +24,7 @@
#include "metal_device.h"
#include <Availability.h>
#include "metal_command_queue.h"
#include "metal_library.h"
#include "metal_types_bridge.h"
@@ -182,8 +183,9 @@
- (nullable id<MTLCommandQueue>)newCommandQueue
{
METAL_NOT_HOOKED();
return [self.real newCommandQueue];
WrappedMTLCommandQueue *wrapped = self.wrappedCPP->newCommandQueue();
MTL::CommandQueue *objc = GetObjCBridge<MTL::CommandQueue *>(wrapped);
return id<MTLCommandQueue>(objc);
}
- (nullable id<MTLCommandQueue>)newCommandQueueWithMaxCommandBufferCount:(NSUInteger)maxCommandBufferCount
+1
View File
@@ -35,6 +35,7 @@ class MetalResourceManager;
enum MetalResourceType
{
eResUnknown = 0,
eResCommandQueue,
eResDevice,
eResLibrary,
eResFunction,
+1
View File
@@ -29,6 +29,7 @@
#include "serialise/serialiser.h"
#define METALCPP_WRAPPED_PROTOCOLS(FUNC) \
FUNC(CommandQueue); \
FUNC(Device); \
FUNC(Function); \
FUNC(Library);
+1 -2
View File
@@ -26,8 +26,7 @@
#include "metal_types.h"
#import <Metal/MTLDevice.h>
#import <Metal/MTLLibrary.h>
#import <Metal/Metal.h>
// clang-format off
#define DECLARE_OBJC_WRAPPED_INTERFACES(CPPTYPE) \
@@ -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"