Hooking for MTLDevice basic new Library APIs

This commit is contained in:
Jake Turner
2022-03-12 20:02:43 +00:00
committed by Baldur Karlsson
parent 88a2b3d74a
commit 5f3203c698
5 changed files with 174 additions and 20 deletions
+30 -3
View File
@@ -29,20 +29,47 @@
#include "common/timing.h"
#include "official/metal-cpp.h"
#include "serialise/serialiser.h"
#include "serialise/serialiser.h"
#include "metal_resources.h"
#include "metal_types.h"
enum class MetalChunk : uint32_t
{
MTLCreateSystemDefaultDevice = (uint32_t)SystemChunk::FirstDriverChunk,
MTLDevice_newDefaultLibrary,
MTLDevice_newLibraryWithSource,
MTLLibrary_newFunctionWithName,
Max
};
DECLARE_REFLECTION_ENUM(MetalChunk);
#define INSTANTIATE_FUNCTION_SERIALISED(CLASS, func, ...) \
template bool CLASS::func(ReadSerialiser &ser, __VA_ARGS__); \
template bool CLASS::func(WriteSerialiser &ser, __VA_ARGS__);
// must be at the start of any function that serialises
#define CACHE_THREAD_SERIALISER() WriteSerialiser &ser = m_WrappedMTLDevice->GetThreadSerialiser();
#define SERIALISE_TIME_CALL(...) \
{ \
WriteSerialiser &ser = m_WrappedMTLDevice->GetThreadSerialiser(); \
ser.ChunkMetadata().timestampMicro = Timing::GetTick(); \
__VA_ARGS__; \
ser.ChunkMetadata().durationMicro = Timing::GetTick() - ser.ChunkMetadata().timestampMicro; \
}
#define DECLARE_FUNCTION_SERIALISED(ret, func, ...) \
ret func(__VA_ARGS__); \
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__));
// 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
// path at compile-time, and the second because we might be just struct-serialising in which case we
// should be doing no work to restore states.
// Writing is unambiguously during capture mode, so we don't have to check both in that case.
#define IsReplayingAndReading() (ser.IsReading() && IsReplayMode(m_WrappedMTLDevice->GetState()))
#ifdef __OBJC__
#define METAL_NOT_HOOKED() \
+123 -9
View File
@@ -23,17 +23,12 @@
******************************************************************************/
#include "metal_device.h"
#include "metal_helpers_bridge.h"
#include "metal_library.h"
#include "metal_manager.h"
WrappedMTLDevice::WrappedMTLDevice(MTL::Device *realMTLDevice, ResourceId objId)
: WrappedMTLObject(realMTLDevice, objId, this, GetStateRef())
{
wrappedObjC = AllocateObjCWrapper(this);
Construct();
GetResourceManager()->AddCurrentResource(objId, this);
}
void WrappedMTLDevice::Construct()
{
objc = AllocateObjCWrapper(this);
m_WrappedMTLDevice = this;
@@ -41,12 +36,131 @@ void WrappedMTLDevice::Construct()
m_ResourceManager = new MetalResourceManager(m_State, this);
RDCASSERT(m_WrappedMTLDevice == this);
GetResourceManager()->AddCurrentResource(objId, this);
}
MTL::Device *WrappedMTLDevice::MTLCreateSystemDefaultDevice(MTL::Device *realMTLDevice)
WrappedMTLDevice *WrappedMTLDevice::MTLCreateSystemDefaultDevice(MTL::Device *realMTLDevice)
{
ResourceId objId = ResourceIDGen::GetNewUniqueID();
WrappedMTLDevice *wrappedMTLDevice = new WrappedMTLDevice(realMTLDevice, objId);
return UnwrapObjC<MTL::Device *>(wrappedMTLDevice);
// return GetObjC<MTL::Device *>(wrappedMTLDevice);
return wrappedMTLDevice;
}
template <typename SerialiserType>
bool WrappedMTLDevice::Serialise_newDefaultLibrary(SerialiserType &ser, WrappedMTLLibrary *library)
{
void *pData;
uint32_t bytesCount;
if(ser.IsWriting())
{
ObjC::Get_defaultLibraryData(pData, bytesCount);
}
SERIALISE_ELEMENT_LOCAL(Library, GetResID(library)).TypedAs("MTLLibrary"_lit);
SERIALISE_ELEMENT(bytesCount);
SERIALISE_ELEMENT_ARRAY(pData, bytesCount);
if(ser.IsWriting())
{
free(pData);
}
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
// TODO: implement RD MTL replay
}
return true;
}
WrappedMTLLibrary *WrappedMTLDevice::newDefaultLibrary()
{
MTL::Library *realMTLLibrary;
SERIALISE_TIME_CALL(realMTLLibrary = Unwrap(this)->newDefaultLibrary());
WrappedMTLLibrary *wrappedMTLLibrary;
ResourceId id = GetResourceManager()->WrapResource(realMTLLibrary, wrappedMTLLibrary);
if(IsCaptureMode(m_State))
{
Chunk *chunk = NULL;
{
CACHE_THREAD_SERIALISER();
SCOPED_SERIALISE_CHUNK(MetalChunk::MTLDevice_newDefaultLibrary);
Serialise_newDefaultLibrary(ser, wrappedMTLLibrary);
chunk = scope.Get();
}
MetalResourceRecord *record = GetResourceManager()->AddResourceRecord(wrappedMTLLibrary);
record->AddChunk(chunk);
GetResourceManager()->MarkResourceFrameReferenced(id, eFrameRef_Read);
}
else
{
// TODO: implement RD MTL replay
// GetResourceManager()->AddLiveResource(id, wrappedMTLLibrary);
}
return wrappedMTLLibrary;
}
template <typename SerialiserType>
bool WrappedMTLDevice::Serialise_newLibraryWithSource(SerialiserType &ser,
WrappedMTLLibrary *library, NS::String *source,
MTL::CompileOptions *options)
{
SERIALISE_ELEMENT_LOCAL(Library, GetResID(library)).TypedAs("MTLLibrary"_lit);
SERIALISE_ELEMENT(source);
// TODO:SERIALISE_ELEMENT(options);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
// TODO: implement RD MTL replay
}
return true;
}
WrappedMTLLibrary *WrappedMTLDevice::newLibraryWithSource(NS::String *source,
MTL::CompileOptions *options,
NS::Error **error)
{
MTL::Library *realMTLLibrary;
SERIALISE_TIME_CALL(realMTLLibrary = Unwrap(this)->newLibrary(source, options, error));
WrappedMTLLibrary *wrappedMTLLibrary;
ResourceId id = GetResourceManager()->WrapResource(realMTLLibrary, wrappedMTLLibrary);
if(IsCaptureMode(m_State))
{
Chunk *chunk = NULL;
{
CACHE_THREAD_SERIALISER();
SCOPED_SERIALISE_CHUNK(MetalChunk::MTLDevice_newLibraryWithSource);
Serialise_newLibraryWithSource(ser, wrappedMTLLibrary, source, options);
chunk = scope.Get();
}
MetalResourceRecord *record = GetResourceManager()->AddResourceRecord(wrappedMTLLibrary);
record->AddChunk(chunk);
GetResourceManager()->MarkResourceFrameReferenced(id, eFrameRef_Read);
}
else
{
// TODO: implement RD MTL replay
// GetResourceManager()->AddLiveResource(id, wrappedMTLLibrary);
}
return wrappedMTLLibrary;
}
template bool WrappedMTLDevice::Serialise_newDefaultLibrary(ReadSerialiser &ser,
WrappedMTLLibrary *library);
template bool WrappedMTLDevice::Serialise_newDefaultLibrary(WriteSerialiser &ser,
WrappedMTLLibrary *library);
template bool WrappedMTLDevice::Serialise_newLibraryWithSource(ReadSerialiser &ser,
WrappedMTLLibrary *library,
NS::String *source,
MTL::CompileOptions *options);
template bool WrappedMTLDevice::Serialise_newLibraryWithSource(WriteSerialiser &ser,
WrappedMTLLibrary *library,
NS::String *source,
MTL::CompileOptions *options);
+11 -3
View File
@@ -34,7 +34,17 @@ class WrappedMTLDevice : public WrappedMTLObject
public:
WrappedMTLDevice(MTL::Device *realMTLDevice, ResourceId objId);
~WrappedMTLDevice() {}
static MTL::Device *MTLCreateSystemDefaultDevice(MTL::Device *realMTLDevice);
static WrappedMTLDevice *MTLCreateSystemDefaultDevice(MTL::Device *realMTLDevice);
WrappedMTLLibrary *newDefaultLibrary();
template <typename SerialiserType>
bool Serialise_newDefaultLibrary(SerialiserType &ser, WrappedMTLLibrary *library);
WrappedMTLLibrary *newLibraryWithSource(NS::String *source, MTL::CompileOptions *options,
NS::Error **error);
template <typename SerialiserType>
bool Serialise_newLibraryWithSource(SerialiserType &ser, WrappedMTLLibrary *library,
NS::String *source, MTL::CompileOptions *options);
CaptureState &GetStateRef() { return m_State; }
CaptureState GetState() { return m_State; }
@@ -47,8 +57,6 @@ public:
};
private:
void Construct();
bool Prepare_InitialState(WrappedMTLObject *res);
uint64_t GetSize_InitialState(ResourceId id, const MetalInitialContents &initial);
template <typename SerialiserType>
@@ -24,6 +24,7 @@
#include "metal_device.h"
#include <Availability.h>
#include "metal_library.h"
#include "metal_types_bridge.h"
// Define Mac SDK versions when compiling with earlier SDKs
@@ -284,8 +285,9 @@
- (nullable id<MTLLibrary>)newDefaultLibrary
{
METAL_NOT_HOOKED();
return [self.real newDefaultLibrary];
WrappedMTLLibrary *wrapped = self.wrappedCPP->newDefaultLibrary();
MTL::Library *objc = GetObjC<MTL::Library *>(wrapped);
return id<MTLLibrary>(objc);
}
- (nullable id<MTLLibrary>)newDefaultLibraryWithBundle:(NSBundle *)bundle
@@ -322,8 +324,10 @@
options:(nullable MTLCompileOptions *)options
error:(__autoreleasing NSError **)error
{
METAL_NOT_HOOKED();
return [self.real newLibraryWithSource:source options:options error:error];
WrappedMTLLibrary *wrapped = self.wrappedCPP->newLibraryWithSource(
(NS::String *)source, (MTL::CompileOptions *)options, (NS::Error **)error);
MTL::Library *objc = GetObjC<MTL::Library *>(wrapped);
return (id<MTLLibrary>)(objc);
}
- (void)newLibraryWithSource:(NSString *)source
+2 -1
View File
@@ -54,7 +54,8 @@ id<MTLDevice> METAL_EXPORT_NAME(MTLCreateSystemDefaultDevice)(void)
}
id<MTLDevice> device = METAL.MTLCreateSystemDefaultDevice();
return id<MTLDevice>(WrappedMTLDevice::MTLCreateSystemDefaultDevice((MTL::Device *)device));
WrappedMTLDevice *wrapped = WrappedMTLDevice::MTLCreateSystemDefaultDevice((MTL::Device *)device);
return id<MTLDevice>(GetObjC<MTL::Device *>(wrapped));
}
/*