From 8a85d153860442ed46ccbb732a5ee6ae01932fb7 Mon Sep 17 00:00:00 2001 From: Jake Turner Date: Fri, 6 May 2022 15:56:44 +0100 Subject: [PATCH] Added wrapped MTLRenderPipelineState & MTLTexture Implemented capture serialisation for APIs: MTLDevice::newRenderPipelineStateWithDescriptor MTLDevice::newTextureWithDescriptor Workaround to prevent Metal capture library assert triggering on the bridge MTLTexture object, add protocol "MTLTextureImplementation" to class "ObjCBridgeMTLTexture" Serialisation for helper types: MTL::TextureDescriptor MTL::RenderPipelineDescriptor MTL::RenderPipelineColorAttachmentDescriptor MTL::PixelFormat MTL::TextureType MTL::PrimitiveTopologyClass MTL::ResourceOptions MTL::CPUCacheMode MTL::StorageMode MTL::HazardTrackingMode MTL::TextureUsage MTL::TextureSwizzleChannels MTL::TextureSwizzle MTL::ColorWriteMask MTL::BlendOperation MTL::BlendFactor MTL::Winding MTL::TessellationFactorFormat MTL::TessellationControlPointIndexType MTL::TessellationFactorStepFunction MTL::TessellationPartitionMode --- renderdoc/driver/metal/CMakeLists.txt | 7 + renderdoc/driver/metal/metal_common.h | 17 + renderdoc/driver/metal/metal_device.cpp | 184 ++++++ renderdoc/driver/metal/metal_device.h | 27 + renderdoc/driver/metal/metal_device_bridge.mm | 27 +- .../metal/metal_render_pipeline_state.cpp | 35 ++ .../metal/metal_render_pipeline_state.h | 41 ++ .../metal_render_pipeline_state_bridge.mm | 152 +++++ renderdoc/driver/metal/metal_resources.cpp | 2 + renderdoc/driver/metal/metal_resources.h | 2 + renderdoc/driver/metal/metal_stringise.cpp | 544 ++++++++++++++++++ renderdoc/driver/metal/metal_texture.cpp | 33 ++ renderdoc/driver/metal/metal_texture.h | 41 ++ .../driver/metal/metal_texture_bridge.mm | 371 ++++++++++++ renderdoc/driver/metal/metal_types.cpp | 497 ++++++++++++++++ renderdoc/driver/metal/metal_types.h | 204 ++++++- 16 files changed, 2177 insertions(+), 7 deletions(-) create mode 100644 renderdoc/driver/metal/metal_render_pipeline_state.cpp create mode 100644 renderdoc/driver/metal/metal_render_pipeline_state.h create mode 100644 renderdoc/driver/metal/metal_render_pipeline_state_bridge.mm create mode 100644 renderdoc/driver/metal/metal_stringise.cpp create mode 100644 renderdoc/driver/metal/metal_texture.cpp create mode 100644 renderdoc/driver/metal/metal_texture.h create mode 100644 renderdoc/driver/metal/metal_texture_bridge.mm diff --git a/renderdoc/driver/metal/CMakeLists.txt b/renderdoc/driver/metal/CMakeLists.txt index 9cd48d67c..86875daf5 100644 --- a/renderdoc/driver/metal/CMakeLists.txt +++ b/renderdoc/driver/metal/CMakeLists.txt @@ -25,6 +25,12 @@ set(sources metal_command_buffer.cpp metal_command_buffer.h metal_command_buffer_bridge.mm + metal_render_pipeline_state.cpp + metal_render_pipeline_state.h + metal_render_pipeline_state_bridge.mm + metal_texture.cpp + metal_texture.h + metal_texture_bridge.mm metal_core.cpp metal_core.h metal_manager.cpp @@ -32,6 +38,7 @@ set(sources metal_init_state.cpp metal_helpers_bridge.h metal_helpers_bridge.mm + metal_stringise.cpp official/metal-cpp.h official/metal-cpp.cpp) diff --git a/renderdoc/driver/metal/metal_common.h b/renderdoc/driver/metal/metal_common.h index bd48af550..4508cc4a6 100644 --- a/renderdoc/driver/metal/metal_common.h +++ b/renderdoc/driver/metal/metal_common.h @@ -44,6 +44,7 @@ enum class MetalChunk : uint32_t MTLDevice_newDepthStencilStateWithDescriptor, MTLDevice_newTextureWithDescriptor, MTLDevice_newTextureWithDescriptor_iosurface, + MTLDevice_newTextureWithDescriptor_nextDrawable, MTLDevice_newSharedTextureWithDescriptor, MTLDevice_newSharedTextureWithHandle, MTLDevice_newSamplerStateWithDescriptor, @@ -103,6 +104,22 @@ enum class MetalChunk : uint32_t MTLCommandBuffer_accelerationStructureCommandEncoder, MTLCommandBuffer_pushDebugGroup, MTLCommandBuffer_popDebugGroup, + MTLTexture_setPurgeableState, + MTLTexture_makeAliasable, + MTLTexture_getBytes, + MTLTexture_getBytes_slice, + MTLTexture_replaceRegion, + MTLTexture_replaceRegion_slice, + MTLTexture_newTextureViewWithPixelFormat, + MTLTexture_newTextureViewWithPixelFormat_subset, + MTLTexture_newTextureViewWithPixelFormat_subset_swizzle, + MTLTexture_newSharedTextureHandle, + MTLTexture_remoteStorageTexture, + MTLTexture_newRemoteTextureViewForDevice, + MTLRenderPipelineState_functionHandleWithFunction, + MTLRenderPipelineState_newVisibleFunctionTableWithDescriptor, + MTLRenderPipelineState_newIntersectionFunctionTableWithDescriptor, + MTLRenderPipelineState_newRenderPipelineStateWithAdditionalBinaryFunctions, Max }; diff --git a/renderdoc/driver/metal/metal_device.cpp b/renderdoc/driver/metal/metal_device.cpp index 1b911e655..d234deea6 100644 --- a/renderdoc/driver/metal/metal_device.cpp +++ b/renderdoc/driver/metal/metal_device.cpp @@ -24,9 +24,12 @@ #include "metal_device.h" #include "metal_command_queue.h" +#include "metal_function.h" #include "metal_helpers_bridge.h" #include "metal_library.h" #include "metal_manager.h" +#include "metal_render_pipeline_state.h" +#include "metal_texture.h" WrappedMTLDevice::WrappedMTLDevice(MTL::Device *realMTLDevice, ResourceId objId) : WrappedMTLObject(realMTLDevice, objId, this, GetStateRef()) @@ -42,12 +45,27 @@ WrappedMTLDevice::WrappedMTLDevice(MTL::Device *realMTLDevice, ResourceId objId) WrappedMTLDevice *WrappedMTLDevice::MTLCreateSystemDefaultDevice(MTL::Device *realMTLDevice) { + MTLFixupForMetalDriverAssert(); ResourceId objId = ResourceIDGen::GetNewUniqueID(); WrappedMTLDevice *wrappedMTLDevice = new WrappedMTLDevice(realMTLDevice, objId); return wrappedMTLDevice; } +void WrappedMTLDevice::MTLFixupForMetalDriverAssert() +{ + static bool s_fixupMetalDriverAssert = false; + if(s_fixupMetalDriverAssert) + return; + + RDCLOG( + "Fixup for Metal Driver debug assert. Adding protocol `MTLTextureImplementation` to " + "`ObjCBridgeMTLTexture`"); + class_addProtocol(objc_lookUpClass("ObjCBridgeMTLTexture"), + objc_getProtocol("MTLTextureImplementation")); + s_fixupMetalDriverAssert = true; +} + // Serialised MTLDevice APIs template @@ -189,6 +207,122 @@ WrappedMTLLibrary *WrappedMTLDevice::newLibraryWithSource(NS::String *source, return wrappedMTLLibrary; } +template +bool WrappedMTLDevice::Serialise_newRenderPipelineStateWithDescriptor( + SerialiserType &ser, WrappedMTLRenderPipelineState *pipelineState, + RDMTL::RenderPipelineDescriptor &descriptor, NS::Error **error) +{ + SERIALISE_ELEMENT_LOCAL(RenderPipelineState, GetResID(pipelineState)) + .TypedAs("MTLRenderPipelineState"_lit); + SERIALISE_ELEMENT(descriptor); + + SERIALISE_CHECK_READ_ERRORS(); + + // TODO: implement RD MTL replay + if(IsReplayingAndReading()) + { + } + return true; +} + +WrappedMTLRenderPipelineState *WrappedMTLDevice::newRenderPipelineStateWithDescriptor( + MTL::RenderPipelineDescriptor *descriptor, NS::Error **error) +{ + MTL::RenderPipelineDescriptor *realDescriptor = descriptor->copy(); + + // realDescriptor needs the real resources + // TODO: need to unwrap more resources see + // RenderPipelineDescriptor::operator MTL::RenderPipelineDescriptor *() + WrappedMTLFunction *wrappedVertexFunction = GetWrapped(descriptor->vertexFunction()); + if(wrappedVertexFunction != NULL) + { + realDescriptor->setVertexFunction(Unwrap(wrappedVertexFunction)); + } + + WrappedMTLFunction *wrappedFragmentFunction = GetWrapped(descriptor->fragmentFunction()); + if(wrappedFragmentFunction != NULL) + { + realDescriptor->setFragmentFunction(Unwrap(wrappedFragmentFunction)); + } + + MTL::RenderPipelineState *realMTLRenderPipelineState; + SERIALISE_TIME_CALL(realMTLRenderPipelineState = + Unwrap(this)->newRenderPipelineState(realDescriptor, error)); + realDescriptor->release(); + + WrappedMTLRenderPipelineState *wrappedMTLRenderPipelineState; + ResourceId id = + GetResourceManager()->WrapResource(realMTLRenderPipelineState, wrappedMTLRenderPipelineState); + if(IsCaptureMode(m_State)) + { + Chunk *chunk = NULL; + { + CACHE_THREAD_SERIALISER(); + SCOPED_SERIALISE_CHUNK(MetalChunk::MTLDevice_newRenderPipelineStateWithDescriptor); + RDMTL::RenderPipelineDescriptor rdDescriptor(descriptor); + Serialise_newRenderPipelineStateWithDescriptor(ser, wrappedMTLRenderPipelineState, + rdDescriptor, error); + chunk = scope.Get(); + } + + MetalResourceRecord *record = + GetResourceManager()->AddResourceRecord(wrappedMTLRenderPipelineState); + record->AddChunk(chunk); + if(wrappedVertexFunction) + { + record->AddParent(GetRecord(wrappedVertexFunction)); + } + if(wrappedFragmentFunction) + { + record->AddParent(GetRecord(wrappedFragmentFunction)); + } + } + else + { + // TODO: implement RD MTL replay + // GetResourceManager()->AddLiveResource(id, *wrappedMTLRenderPipelineState); + } + return wrappedMTLRenderPipelineState; +} + +template +bool WrappedMTLDevice::Serialise_newTextureWithDescriptor(SerialiserType &ser, + WrappedMTLTexture *texture, + RDMTL::TextureDescriptor &descriptor) +{ + SERIALISE_ELEMENT_LOCAL(Texture, GetResID(texture)).TypedAs("MTLTexture"_lit); + SERIALISE_ELEMENT(descriptor); + + SERIALISE_CHECK_READ_ERRORS(); + + if(IsReplayingAndReading()) + { + } + return true; +} + +WrappedMTLTexture *WrappedMTLDevice::newTextureWithDescriptor(MTL::TextureDescriptor *descriptor) +{ + MTL::Texture *realMTLTexture; + SERIALISE_TIME_CALL(realMTLTexture = Unwrap(this)->newTexture(descriptor)); + WrappedMTLTexture *wrappedMTLTexture = + NewTexture(realMTLTexture, descriptor, MetalChunk::MTLDevice_newTextureWithDescriptor); + return wrappedMTLTexture; +} + +WrappedMTLTexture *WrappedMTLDevice::newTextureWithDescriptor(MTL::TextureDescriptor *descriptor, + IOSurfaceRef iosurface, + NS::UInteger plane) +{ + return NewIOSurfaceTextureWithDescriptor(descriptor, iosurface, plane, false); +} + +WrappedMTLTexture *WrappedMTLDevice::nextDrawableTexture(MTL::TextureDescriptor *descriptor, + IOSurfaceRef iosurface, NS::UInteger plane) +{ + return NewIOSurfaceTextureWithDescriptor(descriptor, iosurface, plane, true); +} + // Non-Serialised MTLDevice APIs bool WrappedMTLDevice::isDepth24Stencil8PixelFormatSupported() @@ -320,9 +454,59 @@ bool WrappedMTLDevice::supportsPrimitiveMotionBlur() // End of MTLDevice APIs +WrappedMTLTexture *WrappedMTLDevice::NewTexture(MTL::Texture *realMTLTexture, + MTL::TextureDescriptor *descriptor, + MetalChunk chunkType) +{ + WrappedMTLTexture *wrappedMTLTexture; + ResourceId id = GetResourceManager()->WrapResource(realMTLTexture, wrappedMTLTexture); + if(IsCaptureMode(m_State)) + { + RDMTL::TextureDescriptor rdDescriptor(descriptor); + Chunk *chunk = NULL; + { + CACHE_THREAD_SERIALISER(); + SCOPED_SERIALISE_CHUNK(chunkType); + RDMTL::TextureDescriptor rdDescriptor(descriptor); + Serialise_newTextureWithDescriptor(ser, wrappedMTLTexture, rdDescriptor); + chunk = scope.Get(); + } + MetalResourceRecord *textureRecord = GetResourceManager()->AddResourceRecord(wrappedMTLTexture); + textureRecord->AddChunk(chunk); + } + return wrappedMTLTexture; +} + +WrappedMTLTexture *WrappedMTLDevice::NewIOSurfaceTextureWithDescriptor( + MTL::TextureDescriptor *descriptor, IOSurfaceRef iosurface, NS::UInteger plane, bool nextDrawable) +{ + MTL::Texture *realMTLTexture; + SERIALISE_TIME_CALL(realMTLTexture = Unwrap(this)->newTexture(descriptor, iosurface, plane)); + WrappedMTLTexture *wrappedMTLTexture = + NewTexture(realMTLTexture, descriptor, + nextDrawable ? MetalChunk::MTLDevice_newTextureWithDescriptor_nextDrawable + : MetalChunk::MTLDevice_newTextureWithDescriptor_iosurface); + if(IsCaptureMode(m_State)) + { + { + SCOPED_LOCK(m_PotentialBackBuffersLock); + m_PotentialBackBuffers.insert(wrappedMTLTexture); + } + } + return wrappedMTLTexture; +} + INSTANTIATE_FUNCTION_WITH_RETURN_SERIALISED(WrappedMTLDevice, WrappedMTLCommandQueue *, newCommandQueue); INSTANTIATE_FUNCTION_WITH_RETURN_SERIALISED(WrappedMTLDevice, WrappedMTLLibrary *, newDefaultLibrary); INSTANTIATE_FUNCTION_WITH_RETURN_SERIALISED(WrappedMTLDevice, WrappedMTLLibrary *, newLibraryWithSource, NS::String *source, MTL::CompileOptions *options, NS::Error **error); +INSTANTIATE_FUNCTION_WITH_RETURN_SERIALISED(WrappedMTLDevice, + WrappedMTLRenderPipelineState *renderPipelineState, + newRenderPipelineStateWithDescriptor, + RDMTL::RenderPipelineDescriptor &descriptor, + NS::Error **error); +INSTANTIATE_FUNCTION_WITH_RETURN_SERIALISED(WrappedMTLDevice, WrappedMTLTexture *, + newTextureWithDescriptor, + RDMTL::TextureDescriptor &descriptor); diff --git a/renderdoc/driver/metal/metal_device.h b/renderdoc/driver/metal/metal_device.h index ec26d46c0..83e397d28 100644 --- a/renderdoc/driver/metal/metal_device.h +++ b/renderdoc/driver/metal/metal_device.h @@ -42,6 +42,22 @@ public: DECLARE_FUNCTION_WITH_RETURN_SERIALISED(WrappedMTLLibrary *, newLibraryWithSource, NS::String *source, MTL::CompileOptions *options, NS::Error **error); + WrappedMTLRenderPipelineState *newRenderPipelineStateWithDescriptor( + MTL::RenderPipelineDescriptor *descriptor, NS::Error **error); + template + bool Serialise_newRenderPipelineStateWithDescriptor(SerialiserType &ser, + WrappedMTLRenderPipelineState *, + RDMTL::RenderPipelineDescriptor &descriptor, + 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 + bool Serialise_newTextureWithDescriptor(SerialiserType &ser, WrappedMTLTexture *, + RDMTL::TextureDescriptor &descriptor); + // Non-Serialised MTLDevice APIs bool isDepth24Stencil8PixelFormatSupported(); MTL::ReadWriteTextureTier readWriteTextureSupport(); @@ -81,6 +97,7 @@ public: }; private: + static void MTLFixupForMetalDriverAssert(); bool Prepare_InitialState(WrappedMTLObject *res); uint64_t GetSize_InitialState(ResourceId id, const MetalInitialContents &initial); template @@ -89,8 +106,18 @@ private: void Create_InitialState(ResourceId id, WrappedMTLObject *live, bool hasData); void Apply_InitialState(WrappedMTLObject *live, const MetalInitialContents &initial); + WrappedMTLTexture *NewTexture(MTL::Texture *realMTLTexture, MTL::TextureDescriptor *descriptor, + MetalChunk chunkType); + WrappedMTLTexture *NewIOSurfaceTextureWithDescriptor(MTL::TextureDescriptor *descriptor, + IOSurfaceRef iosurface, NS::UInteger plane, + bool nextDrawable); + MetalResourceManager *m_ResourceManager; + // Back buffer and swap chain emulation + Threading::CriticalSection m_PotentialBackBuffersLock; + std::unordered_set m_PotentialBackBuffers; + CaptureState m_State; uint64_t threadSerialiserTLSSlot; diff --git a/renderdoc/driver/metal/metal_device_bridge.mm b/renderdoc/driver/metal/metal_device_bridge.mm index abe0aa475..d691128d5 100644 --- a/renderdoc/driver/metal/metal_device_bridge.mm +++ b/renderdoc/driver/metal/metal_device_bridge.mm @@ -257,8 +257,8 @@ - (nullable id)newTextureWithDescriptor:(MTLTextureDescriptor *)descriptor { - METAL_NOT_HOOKED(); - return [self.real newTextureWithDescriptor:descriptor]; + return id( + GetWrapped(self)->newTextureWithDescriptor((MTL::TextureDescriptor *)descriptor)); } - (nullable id)newTextureWithDescriptor:(MTLTextureDescriptor *)descriptor @@ -266,8 +266,23 @@ plane:(NSUInteger)plane API_AVAILABLE(macos(10.11), ios(11.0)) { - METAL_NOT_HOOKED(); - return [self.real newTextureWithDescriptor:descriptor iosurface:iosurface plane:plane]; + 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(GetWrapped(self)->nextDrawableTexture( + (MTL::TextureDescriptor *)descriptor, iosurface, plane)); + } + return id(GetWrapped(self)->newTextureWithDescriptor( + (MTL::TextureDescriptor *)descriptor, iosurface, plane)); } - (nullable id)newSharedTextureWithDescriptor:(MTLTextureDescriptor *)descriptor @@ -366,8 +381,8 @@ newRenderPipelineStateWithDescriptor:(MTLRenderPipelineDescriptor *)descriptor error:(__autoreleasing NSError **)error { - METAL_NOT_HOOKED(); - return [self.real newRenderPipelineStateWithDescriptor:descriptor error:error]; + return id(GetWrapped(self)->newRenderPipelineStateWithDescriptor( + (MTL::RenderPipelineDescriptor *)descriptor, (NS::Error **)error)); } - (nullable id) diff --git a/renderdoc/driver/metal/metal_render_pipeline_state.cpp b/renderdoc/driver/metal/metal_render_pipeline_state.cpp new file mode 100644 index 000000000..6e9a50047 --- /dev/null +++ b/renderdoc/driver/metal/metal_render_pipeline_state.cpp @@ -0,0 +1,35 @@ +/****************************************************************************** + * 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_render_pipeline_state.h" +#include "metal_device.h" + +WrappedMTLRenderPipelineState::WrappedMTLRenderPipelineState( + MTL::RenderPipelineState *realMTLRenderPipelineState, ResourceId objId, + WrappedMTLDevice *wrappedMTLDevice) + : WrappedMTLObject(realMTLRenderPipelineState, objId, wrappedMTLDevice, + wrappedMTLDevice->GetStateRef()) +{ + AllocateObjCBridge(this); +} diff --git a/renderdoc/driver/metal/metal_render_pipeline_state.h b/renderdoc/driver/metal/metal_render_pipeline_state.h new file mode 100644 index 000000000..d5f9f137d --- /dev/null +++ b/renderdoc/driver/metal/metal_render_pipeline_state.h @@ -0,0 +1,41 @@ +/****************************************************************************** + * 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 WrappedMTLRenderPipelineState : public WrappedMTLObject +{ +public: + WrappedMTLRenderPipelineState(MTL::RenderPipelineState *realMTLRenderPipelineState, + ResourceId objId, WrappedMTLDevice *wrappedMTLDevice); + + enum + { + TypeEnum = eResRenderPipelineState + }; + +private: +}; diff --git a/renderdoc/driver/metal/metal_render_pipeline_state_bridge.mm b/renderdoc/driver/metal/metal_render_pipeline_state_bridge.mm new file mode 100644 index 000000000..76f1362fa --- /dev/null +++ b/renderdoc/driver/metal/metal_render_pipeline_state_bridge.mm @@ -0,0 +1,152 @@ +/****************************************************************************** + * 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_render_pipeline_state.h" +#include "metal_types_bridge.h" + +// Bridge for MTLRenderPipelineState +@implementation ObjCBridgeMTLRenderPipelineState + +// ObjCBridgeMTLRenderPipelineState specific +- (id)real +{ + return id(Unwrap(GetWrapped(self))); +} + +// Silence compiler warning +// error: method possibly missing a [super dealloc] call [-Werror,-Wobjc-missing-super-calls] +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-missing-super-calls" +- (void)dealloc +{ + GetWrapped(self)->Dealloc(); +} +#pragma clang diagnostic pop + +// Use the real MTLRenderPipelineState to find methods from messages +- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector +{ + id fwd = self.real; + return [fwd methodSignatureForSelector:aSelector]; +} + +// Forward any unknown messages to the real MTLRenderPipelineState +- (void)forwardInvocation:(NSInvocation *)invocation +{ + SEL aSelector = [invocation selector]; + + if([self.real respondsToSelector:aSelector]) + [invocation invokeWithTarget:self.real]; + else + [super forwardInvocation:invocation]; +} + +// MTLRenderPipelineState : based on the protocol defined in +// Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Metal.framework/Headers/MTLRenderPipeline.h + +- (nullable NSString *)label +{ + return self.real.label; +} + +- (id)device +{ + return id(GetWrapped(self)->GetDevice()); +} + +- (NSUInteger)maxTotalThreadsPerThreadgroup + API_AVAILABLE(macos(11.0), macCatalyst(14.0), ios(11.0), tvos(14.5)) +{ + return self.real.maxTotalThreadsPerThreadgroup; +} + +- (BOOL)threadgroupSizeMatchesTileSize + API_AVAILABLE(macos(11.0), macCatalyst(14.0), ios(11.0), tvos(14.5)) +{ + return self.real.threadgroupSizeMatchesTileSize; +} + +- (NSUInteger)imageblockSampleLength + API_AVAILABLE(macos(11.0), macCatalyst(14.0), ios(11.0), tvos(14.5)) +{ + return self.real.imageblockSampleLength; +} + +- (NSUInteger)imageblockMemoryLengthForDimensions:(MTLSize)imageblockDimensions + API_AVAILABLE(macos(11.0), macCatalyst(14.0), ios(11.0), tvos(14.5)) +{ + return [self.real imageblockMemoryLengthForDimensions:imageblockDimensions]; +} + +- (BOOL)supportIndirectCommandBuffers API_AVAILABLE(macos(10.14), ios(12.0)) +{ + return self.real.supportIndirectCommandBuffers; +} + +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_12_0 +- (nullable id)functionHandleWithFunction:(id)function + stage:(MTLRenderStages)stage + API_AVAILABLE(macos(12.0), ios(15.0)) +{ + METAL_NOT_HOOKED(); + return [self.real functionHandleWithFunction:function stage:stage]; +} +#endif + +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_12_0 +- (nullable id)newVisibleFunctionTableWithDescriptor: + (MTLVisibleFunctionTableDescriptor *__nonnull)descriptor + stage:(MTLRenderStages)stage + API_AVAILABLE(macos(12.0), ios(15.0)) +{ + METAL_NOT_HOOKED(); + return [self.real newVisibleFunctionTableWithDescriptor:descriptor stage:stage]; +} +#endif + +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_12_0 +- (nullable id) +newIntersectionFunctionTableWithDescriptor:(MTLIntersectionFunctionTableDescriptor *_Nonnull)descriptor + stage:(MTLRenderStages)stage + API_AVAILABLE(macos(12.0), ios(15.0)) +{ + METAL_NOT_HOOKED(); + return [self.real newIntersectionFunctionTableWithDescriptor:descriptor stage:stage]; +} +#endif + +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_12_0 +- (nullable id) +newRenderPipelineStateWithAdditionalBinaryFunctions: + (nonnull MTLRenderPipelineFunctionsDescriptor *)additionalBinaryFunctions + error:(__autoreleasing NSError **)error + API_AVAILABLE(macos(12.0), ios(15.0)) +{ + METAL_NOT_HOOKED(); + return [self.real newRenderPipelineStateWithAdditionalBinaryFunctions:additionalBinaryFunctions + error:error]; +} +#endif + +@end diff --git a/renderdoc/driver/metal/metal_resources.cpp b/renderdoc/driver/metal/metal_resources.cpp index c7ba6e71a..4f22ce23b 100644 --- a/renderdoc/driver/metal/metal_resources.cpp +++ b/renderdoc/driver/metal/metal_resources.cpp @@ -28,6 +28,8 @@ #include "metal_device.h" #include "metal_function.h" #include "metal_library.h" +#include "metal_render_pipeline_state.h" +#include "metal_texture.h" ResourceId GetResID(WrappedMTLObject *obj) { diff --git a/renderdoc/driver/metal/metal_resources.h b/renderdoc/driver/metal/metal_resources.h index 104a289d9..7ab6db884 100644 --- a/renderdoc/driver/metal/metal_resources.h +++ b/renderdoc/driver/metal/metal_resources.h @@ -40,6 +40,8 @@ enum MetalResourceType eResDevice, eResLibrary, eResFunction, + eResRenderPipelineState, + eResTexture }; DECLARE_REFLECTION_ENUM(MetalResourceType); diff --git a/renderdoc/driver/metal/metal_stringise.cpp b/renderdoc/driver/metal/metal_stringise.cpp new file mode 100644 index 000000000..82e6a5214 --- /dev/null +++ b/renderdoc/driver/metal/metal_stringise.cpp @@ -0,0 +1,544 @@ +/****************************************************************************** + * 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_common.h" + +#define MTL_STRINGISE_ENUM(a) STRINGISE_ENUM_CLASS_NAMED(a, "MTL" #a) +#define MTL_STRINGISE_BITFIELD_BIT(a) STRINGISE_BITFIELD_CLASS_BIT_NAMED(a, "MTL" #a) +#define MTL_STRINGISE_BITFIELD_VALUE(a) STRINGISE_BITFIELD_CLASS_VALUE_NAMED(a, "MTL" #a) + +template <> +rdcstr DoStringise(const MTL::Mutability &el) +{ + BEGIN_ENUM_STRINGISE(MTL::Mutability) + { + MTL_STRINGISE_ENUM(MutabilityDefault); + MTL_STRINGISE_ENUM(MutabilityMutable); + MTL_STRINGISE_ENUM(MutabilityImmutable); + } + END_ENUM_STRINGISE() +} + +template <> +rdcstr DoStringise(const MTL::PixelFormat &el) +{ + BEGIN_ENUM_STRINGISE(MTL::PixelFormat) + { + MTL_STRINGISE_ENUM(PixelFormatInvalid); + MTL_STRINGISE_ENUM(PixelFormatA8Unorm); + MTL_STRINGISE_ENUM(PixelFormatR8Unorm); + MTL_STRINGISE_ENUM(PixelFormatR8Unorm_sRGB); + MTL_STRINGISE_ENUM(PixelFormatR8Snorm); + MTL_STRINGISE_ENUM(PixelFormatR8Uint); + MTL_STRINGISE_ENUM(PixelFormatR8Sint); + MTL_STRINGISE_ENUM(PixelFormatR16Unorm); + MTL_STRINGISE_ENUM(PixelFormatR16Snorm); + MTL_STRINGISE_ENUM(PixelFormatR16Uint); + MTL_STRINGISE_ENUM(PixelFormatR16Sint); + MTL_STRINGISE_ENUM(PixelFormatR16Float); + MTL_STRINGISE_ENUM(PixelFormatRG8Unorm); + MTL_STRINGISE_ENUM(PixelFormatRG8Unorm_sRGB); + MTL_STRINGISE_ENUM(PixelFormatRG8Snorm); + MTL_STRINGISE_ENUM(PixelFormatRG8Uint); + MTL_STRINGISE_ENUM(PixelFormatRG8Sint); + MTL_STRINGISE_ENUM(PixelFormatB5G6R5Unorm); + MTL_STRINGISE_ENUM(PixelFormatA1BGR5Unorm); + MTL_STRINGISE_ENUM(PixelFormatABGR4Unorm); + MTL_STRINGISE_ENUM(PixelFormatBGR5A1Unorm); + MTL_STRINGISE_ENUM(PixelFormatR32Uint); + MTL_STRINGISE_ENUM(PixelFormatR32Sint); + MTL_STRINGISE_ENUM(PixelFormatR32Float); + MTL_STRINGISE_ENUM(PixelFormatRG16Unorm); + MTL_STRINGISE_ENUM(PixelFormatRG16Snorm); + MTL_STRINGISE_ENUM(PixelFormatRG16Uint); + MTL_STRINGISE_ENUM(PixelFormatRG16Sint); + MTL_STRINGISE_ENUM(PixelFormatRG16Float); + MTL_STRINGISE_ENUM(PixelFormatRGBA8Unorm); + MTL_STRINGISE_ENUM(PixelFormatRGBA8Unorm_sRGB); + MTL_STRINGISE_ENUM(PixelFormatRGBA8Snorm); + MTL_STRINGISE_ENUM(PixelFormatRGBA8Uint); + MTL_STRINGISE_ENUM(PixelFormatRGBA8Sint); + MTL_STRINGISE_ENUM(PixelFormatBGRA8Unorm); + MTL_STRINGISE_ENUM(PixelFormatBGRA8Unorm_sRGB); + MTL_STRINGISE_ENUM(PixelFormatRGB10A2Unorm); + MTL_STRINGISE_ENUM(PixelFormatRGB10A2Uint); + MTL_STRINGISE_ENUM(PixelFormatRG11B10Float); + MTL_STRINGISE_ENUM(PixelFormatRGB9E5Float); + MTL_STRINGISE_ENUM(PixelFormatBGR10A2Unorm); + MTL_STRINGISE_ENUM(PixelFormatRG32Uint); + MTL_STRINGISE_ENUM(PixelFormatRG32Sint); + MTL_STRINGISE_ENUM(PixelFormatRG32Float); + MTL_STRINGISE_ENUM(PixelFormatRGBA16Unorm); + MTL_STRINGISE_ENUM(PixelFormatRGBA16Snorm); + MTL_STRINGISE_ENUM(PixelFormatRGBA16Uint); + MTL_STRINGISE_ENUM(PixelFormatRGBA16Sint); + MTL_STRINGISE_ENUM(PixelFormatRGBA16Float); + MTL_STRINGISE_ENUM(PixelFormatRGBA32Uint); + MTL_STRINGISE_ENUM(PixelFormatRGBA32Sint); + MTL_STRINGISE_ENUM(PixelFormatRGBA32Float); + MTL_STRINGISE_ENUM(PixelFormatBC1_RGBA); + MTL_STRINGISE_ENUM(PixelFormatBC1_RGBA_sRGB); + MTL_STRINGISE_ENUM(PixelFormatBC2_RGBA); + MTL_STRINGISE_ENUM(PixelFormatBC2_RGBA_sRGB); + MTL_STRINGISE_ENUM(PixelFormatBC3_RGBA); + MTL_STRINGISE_ENUM(PixelFormatBC3_RGBA_sRGB); + MTL_STRINGISE_ENUM(PixelFormatBC4_RUnorm); + MTL_STRINGISE_ENUM(PixelFormatBC4_RSnorm); + MTL_STRINGISE_ENUM(PixelFormatBC5_RGUnorm); + MTL_STRINGISE_ENUM(PixelFormatBC5_RGSnorm); + MTL_STRINGISE_ENUM(PixelFormatBC6H_RGBFloat); + MTL_STRINGISE_ENUM(PixelFormatBC6H_RGBUfloat); + MTL_STRINGISE_ENUM(PixelFormatBC7_RGBAUnorm); + MTL_STRINGISE_ENUM(PixelFormatBC7_RGBAUnorm_sRGB); + MTL_STRINGISE_ENUM(PixelFormatPVRTC_RGB_2BPP); + MTL_STRINGISE_ENUM(PixelFormatPVRTC_RGB_2BPP_sRGB); + MTL_STRINGISE_ENUM(PixelFormatPVRTC_RGB_4BPP); + MTL_STRINGISE_ENUM(PixelFormatPVRTC_RGB_4BPP_sRGB); + MTL_STRINGISE_ENUM(PixelFormatPVRTC_RGBA_2BPP); + MTL_STRINGISE_ENUM(PixelFormatPVRTC_RGBA_2BPP_sRGB); + MTL_STRINGISE_ENUM(PixelFormatPVRTC_RGBA_4BPP); + MTL_STRINGISE_ENUM(PixelFormatPVRTC_RGBA_4BPP_sRGB); + MTL_STRINGISE_ENUM(PixelFormatEAC_R11Unorm); + MTL_STRINGISE_ENUM(PixelFormatEAC_R11Snorm); + MTL_STRINGISE_ENUM(PixelFormatEAC_RG11Unorm); + MTL_STRINGISE_ENUM(PixelFormatEAC_RG11Snorm); + MTL_STRINGISE_ENUM(PixelFormatEAC_RGBA8); + MTL_STRINGISE_ENUM(PixelFormatEAC_RGBA8_sRGB); + MTL_STRINGISE_ENUM(PixelFormatETC2_RGB8); + MTL_STRINGISE_ENUM(PixelFormatETC2_RGB8_sRGB); + MTL_STRINGISE_ENUM(PixelFormatETC2_RGB8A1); + MTL_STRINGISE_ENUM(PixelFormatETC2_RGB8A1_sRGB); + MTL_STRINGISE_ENUM(PixelFormatASTC_4x4_sRGB); + MTL_STRINGISE_ENUM(PixelFormatASTC_5x4_sRGB); + MTL_STRINGISE_ENUM(PixelFormatASTC_5x5_sRGB); + MTL_STRINGISE_ENUM(PixelFormatASTC_6x5_sRGB); + MTL_STRINGISE_ENUM(PixelFormatASTC_6x6_sRGB); + MTL_STRINGISE_ENUM(PixelFormatASTC_8x5_sRGB); + MTL_STRINGISE_ENUM(PixelFormatASTC_8x6_sRGB); + MTL_STRINGISE_ENUM(PixelFormatASTC_8x8_sRGB); + MTL_STRINGISE_ENUM(PixelFormatASTC_10x5_sRGB); + MTL_STRINGISE_ENUM(PixelFormatASTC_10x6_sRGB); + MTL_STRINGISE_ENUM(PixelFormatASTC_10x8_sRGB); + MTL_STRINGISE_ENUM(PixelFormatASTC_10x10_sRGB); + MTL_STRINGISE_ENUM(PixelFormatASTC_12x10_sRGB); + MTL_STRINGISE_ENUM(PixelFormatASTC_12x12_sRGB); + MTL_STRINGISE_ENUM(PixelFormatASTC_4x4_LDR); + MTL_STRINGISE_ENUM(PixelFormatASTC_5x4_LDR); + MTL_STRINGISE_ENUM(PixelFormatASTC_5x5_LDR); + MTL_STRINGISE_ENUM(PixelFormatASTC_6x5_LDR); + MTL_STRINGISE_ENUM(PixelFormatASTC_6x6_LDR); + MTL_STRINGISE_ENUM(PixelFormatASTC_8x5_LDR); + MTL_STRINGISE_ENUM(PixelFormatASTC_8x6_LDR); + MTL_STRINGISE_ENUM(PixelFormatASTC_8x8_LDR); + MTL_STRINGISE_ENUM(PixelFormatASTC_10x5_LDR); + MTL_STRINGISE_ENUM(PixelFormatASTC_10x6_LDR); + MTL_STRINGISE_ENUM(PixelFormatASTC_10x8_LDR); + MTL_STRINGISE_ENUM(PixelFormatASTC_10x10_LDR); + MTL_STRINGISE_ENUM(PixelFormatASTC_12x10_LDR); + MTL_STRINGISE_ENUM(PixelFormatASTC_12x12_LDR); + MTL_STRINGISE_ENUM(PixelFormatASTC_4x4_HDR); + MTL_STRINGISE_ENUM(PixelFormatASTC_5x4_HDR); + MTL_STRINGISE_ENUM(PixelFormatASTC_5x5_HDR); + MTL_STRINGISE_ENUM(PixelFormatASTC_6x5_HDR); + MTL_STRINGISE_ENUM(PixelFormatASTC_6x6_HDR); + MTL_STRINGISE_ENUM(PixelFormatASTC_8x5_HDR); + MTL_STRINGISE_ENUM(PixelFormatASTC_8x6_HDR); + MTL_STRINGISE_ENUM(PixelFormatASTC_8x8_HDR); + MTL_STRINGISE_ENUM(PixelFormatASTC_10x5_HDR); + MTL_STRINGISE_ENUM(PixelFormatASTC_10x6_HDR); + MTL_STRINGISE_ENUM(PixelFormatASTC_10x8_HDR); + MTL_STRINGISE_ENUM(PixelFormatASTC_10x10_HDR); + MTL_STRINGISE_ENUM(PixelFormatASTC_12x10_HDR); + MTL_STRINGISE_ENUM(PixelFormatASTC_12x12_HDR); + MTL_STRINGISE_ENUM(PixelFormatGBGR422); + MTL_STRINGISE_ENUM(PixelFormatBGRG422); + MTL_STRINGISE_ENUM(PixelFormatDepth16Unorm); + MTL_STRINGISE_ENUM(PixelFormatDepth32Float); + MTL_STRINGISE_ENUM(PixelFormatStencil8); + MTL_STRINGISE_ENUM(PixelFormatDepth24Unorm_Stencil8); + MTL_STRINGISE_ENUM(PixelFormatDepth32Float_Stencil8); + MTL_STRINGISE_ENUM(PixelFormatX32_Stencil8); + MTL_STRINGISE_ENUM(PixelFormatX24_Stencil8); + MTL_STRINGISE_ENUM(PixelFormatBGRA10_XR); + MTL_STRINGISE_ENUM(PixelFormatBGRA10_XR_sRGB); + MTL_STRINGISE_ENUM(PixelFormatBGR10_XR); + MTL_STRINGISE_ENUM(PixelFormatBGR10_XR_sRGB); + } + END_ENUM_STRINGISE() +} + +template <> +rdcstr DoStringise(const MTL::VertexFormat &el) +{ + BEGIN_ENUM_STRINGISE(MTL::VertexFormat) + { + MTL_STRINGISE_ENUM(VertexFormatInvalid); + MTL_STRINGISE_ENUM(VertexFormatUChar2); + MTL_STRINGISE_ENUM(VertexFormatUChar3); + MTL_STRINGISE_ENUM(VertexFormatUChar4); + MTL_STRINGISE_ENUM(VertexFormatChar2); + MTL_STRINGISE_ENUM(VertexFormatChar3); + MTL_STRINGISE_ENUM(VertexFormatChar4); + MTL_STRINGISE_ENUM(VertexFormatUChar2Normalized); + MTL_STRINGISE_ENUM(VertexFormatUChar3Normalized); + MTL_STRINGISE_ENUM(VertexFormatUChar4Normalized); + MTL_STRINGISE_ENUM(VertexFormatChar2Normalized); + MTL_STRINGISE_ENUM(VertexFormatChar3Normalized); + MTL_STRINGISE_ENUM(VertexFormatChar4Normalized); + MTL_STRINGISE_ENUM(VertexFormatUShort2); + MTL_STRINGISE_ENUM(VertexFormatUShort3); + MTL_STRINGISE_ENUM(VertexFormatUShort4); + MTL_STRINGISE_ENUM(VertexFormatShort2); + MTL_STRINGISE_ENUM(VertexFormatShort3); + MTL_STRINGISE_ENUM(VertexFormatShort4); + MTL_STRINGISE_ENUM(VertexFormatUShort2Normalized); + MTL_STRINGISE_ENUM(VertexFormatUShort3Normalized); + MTL_STRINGISE_ENUM(VertexFormatUShort4Normalized); + MTL_STRINGISE_ENUM(VertexFormatShort2Normalized); + MTL_STRINGISE_ENUM(VertexFormatShort3Normalized); + MTL_STRINGISE_ENUM(VertexFormatShort4Normalized); + MTL_STRINGISE_ENUM(VertexFormatHalf2); + MTL_STRINGISE_ENUM(VertexFormatHalf3); + MTL_STRINGISE_ENUM(VertexFormatHalf4); + MTL_STRINGISE_ENUM(VertexFormatFloat); + MTL_STRINGISE_ENUM(VertexFormatFloat2); + MTL_STRINGISE_ENUM(VertexFormatFloat3); + MTL_STRINGISE_ENUM(VertexFormatFloat4); + MTL_STRINGISE_ENUM(VertexFormatInt); + MTL_STRINGISE_ENUM(VertexFormatInt2); + MTL_STRINGISE_ENUM(VertexFormatInt3); + MTL_STRINGISE_ENUM(VertexFormatInt4); + MTL_STRINGISE_ENUM(VertexFormatUInt); + MTL_STRINGISE_ENUM(VertexFormatUInt2); + MTL_STRINGISE_ENUM(VertexFormatUInt3); + MTL_STRINGISE_ENUM(VertexFormatUInt4); + MTL_STRINGISE_ENUM(VertexFormatInt1010102Normalized); + MTL_STRINGISE_ENUM(VertexFormatUInt1010102Normalized); + MTL_STRINGISE_ENUM(VertexFormatUChar4Normalized_BGRA); + MTL_STRINGISE_ENUM(VertexFormatUChar); + MTL_STRINGISE_ENUM(VertexFormatChar); + MTL_STRINGISE_ENUM(VertexFormatUCharNormalized); + MTL_STRINGISE_ENUM(VertexFormatCharNormalized); + MTL_STRINGISE_ENUM(VertexFormatUShort); + MTL_STRINGISE_ENUM(VertexFormatShort); + MTL_STRINGISE_ENUM(VertexFormatUShortNormalized); + MTL_STRINGISE_ENUM(VertexFormatShortNormalized); + MTL_STRINGISE_ENUM(VertexFormatHalf); + } + END_ENUM_STRINGISE() +} + +template <> +rdcstr DoStringise(const MTL::VertexStepFunction &el) +{ + BEGIN_ENUM_STRINGISE(MTL::VertexStepFunction) + { + MTL_STRINGISE_ENUM(VertexStepFunctionConstant); + MTL_STRINGISE_ENUM(VertexStepFunctionPerVertex); + MTL_STRINGISE_ENUM(VertexStepFunctionPerInstance); + MTL_STRINGISE_ENUM(VertexStepFunctionPerPatch); + MTL_STRINGISE_ENUM(VertexStepFunctionPerPatchControlPoint); + } + END_ENUM_STRINGISE() +} + +template <> +rdcstr DoStringise(const MTL::PrimitiveTopologyClass &el) +{ + BEGIN_ENUM_STRINGISE(MTL::PrimitiveTopologyClass) + { + MTL_STRINGISE_ENUM(PrimitiveTopologyClassUnspecified); + MTL_STRINGISE_ENUM(PrimitiveTopologyClassPoint); + MTL_STRINGISE_ENUM(PrimitiveTopologyClassLine); + MTL_STRINGISE_ENUM(PrimitiveTopologyClassTriangle); + } + END_ENUM_STRINGISE() +} + +template <> +rdcstr DoStringise(const MTL::Winding &el) +{ + BEGIN_ENUM_STRINGISE(MTL::Winding) + { + MTL_STRINGISE_ENUM(WindingClockwise); + MTL_STRINGISE_ENUM(WindingCounterClockwise); + } + END_ENUM_STRINGISE() +} + +template <> +rdcstr DoStringise(const MTL::TessellationFactorFormat &el) +{ + BEGIN_ENUM_STRINGISE(MTL::TessellationFactorFormat) + { + MTL_STRINGISE_ENUM(TessellationFactorFormatHalf); + } + END_ENUM_STRINGISE() +} + +template <> +rdcstr DoStringise(const MTL::TessellationControlPointIndexType &el) +{ + BEGIN_ENUM_STRINGISE(MTL::TessellationControlPointIndexType) + { + MTL_STRINGISE_ENUM(TessellationControlPointIndexTypeNone); + MTL_STRINGISE_ENUM(TessellationControlPointIndexTypeUInt16); + MTL_STRINGISE_ENUM(TessellationControlPointIndexTypeUInt32); + } + END_ENUM_STRINGISE() +} + +template <> +rdcstr DoStringise(const MTL::TessellationFactorStepFunction &el) +{ + BEGIN_ENUM_STRINGISE(MTL::TessellationFactorStepFunction) + { + MTL_STRINGISE_ENUM(TessellationFactorStepFunctionConstant); + MTL_STRINGISE_ENUM(TessellationFactorStepFunctionPerPatch); + MTL_STRINGISE_ENUM(TessellationFactorStepFunctionPerInstance); + MTL_STRINGISE_ENUM(TessellationFactorStepFunctionPerPatchAndPerInstance); + } + END_ENUM_STRINGISE() +} + +template <> +rdcstr DoStringise(const MTL::TessellationPartitionMode &el) +{ + BEGIN_ENUM_STRINGISE(MTL::TessellationPartitionMode) + { + MTL_STRINGISE_ENUM(TessellationPartitionModePow2); + MTL_STRINGISE_ENUM(TessellationPartitionModeInteger); + MTL_STRINGISE_ENUM(TessellationPartitionModeFractionalOdd); + MTL_STRINGISE_ENUM(TessellationPartitionModeFractionalEven); + } + END_ENUM_STRINGISE() +} + +template <> +rdcstr DoStringise(const MTL::CPUCacheMode &el) +{ + BEGIN_ENUM_STRINGISE(MTL::CPUCacheMode) + { + MTL_STRINGISE_ENUM(CPUCacheModeDefaultCache); + MTL_STRINGISE_ENUM(CPUCacheModeWriteCombined); + } + END_ENUM_STRINGISE() +} + +template <> +rdcstr DoStringise(const MTL::StorageMode &el) +{ + BEGIN_ENUM_STRINGISE(MTL::StorageMode) + { + MTL_STRINGISE_ENUM(StorageModeShared); + MTL_STRINGISE_ENUM(StorageModeManaged); + MTL_STRINGISE_ENUM(StorageModePrivate); + MTL_STRINGISE_ENUM(StorageModeMemoryless); + } + END_ENUM_STRINGISE() +} + +template <> +rdcstr DoStringise(const MTL::HazardTrackingMode &el) +{ + BEGIN_ENUM_STRINGISE(MTL::HazardTrackingMode) + { + MTL_STRINGISE_ENUM(HazardTrackingModeDefault); + MTL_STRINGISE_ENUM(HazardTrackingModeUntracked); + MTL_STRINGISE_ENUM(HazardTrackingModeTracked); + } + END_ENUM_STRINGISE() +} + +template <> +rdcstr DoStringise(const MTL::ResourceOptions &el) +{ + uint64_t local = (uint64_t)el; + rdcstr ret; + // MTL::ResourceOptions is a combined value containing + // MTL::CPUCacheMode, MTL::StorageMode, MTL::HazardTrackingMode + + // The same value (0) is used for + // MTLResourceCPUCacheModeDefaultCache + // MTLResourceStorageModeShared + // MTLResourceHazardTrackingModeDefault + + if((el & MTL::ResourceCPUCacheModeWriteCombined) == MTL::ResourceCPUCacheModeWriteCombined) + { + local &= ~uint64_t(MTL::ResourceCPUCacheModeWriteCombined); + ret += " | MTLResourceCPUCacheModeWriteCombined"; + } + else + { + ret += " | MTLResourceCPUCacheModeDefaultCache"; + } + + if((el & MTL::ResourceStorageModeManaged) == MTL::ResourceStorageModeManaged) + { + local &= ~uint64_t(MTL::ResourceStorageModeManaged); + ret += " | MTLResourceStorageModeManaged"; + } + else if((el & MTL::ResourceStorageModePrivate) == MTL::ResourceStorageModePrivate) + { + local &= ~uint64_t(MTL::ResourceStorageModePrivate); + ret += " | MTLResourceStorageModePrivate"; + } + else if((el & MTL::ResourceStorageModeMemoryless) == MTL::ResourceStorageModeMemoryless) + { + local &= ~uint64_t(MTL::ResourceStorageModeMemoryless); + ret += " | MTLResourceStorageModeMemoryless"; + } + else + { + ret += " | MTLResourceStorageModeShared"; + } + + if((el & MTL::ResourceHazardTrackingModeUntracked) == MTL::ResourceHazardTrackingModeUntracked) + { + local &= ~uint64_t(MTL::ResourceHazardTrackingModeUntracked); + ret += " | MTLResourceHazardTrackingModeUntracked"; + } + else if((el & MTL::ResourceHazardTrackingModeTracked) == MTL::ResourceHazardTrackingModeTracked) + { + local &= ~uint64_t(MTL::ResourceHazardTrackingModeTracked); + ret += " | MTLResourceHazardTrackingModeTracked"; + } + else + { + ret += " | MTLResourceHazardTrackingModeDefault"; + } + + if(local) + { + ret += " | MTLResourceOptions (" + ToStr((uint32_t)local) + ")"; + } + + ret = ret.substr(3); + return ret; +} + +template <> +rdcstr DoStringise(const MTL::TextureType &el) +{ + BEGIN_ENUM_STRINGISE(MTL::TextureType) + { + MTL_STRINGISE_ENUM(TextureType1D); + MTL_STRINGISE_ENUM(TextureType1DArray); + MTL_STRINGISE_ENUM(TextureType2D); + MTL_STRINGISE_ENUM(TextureType2DArray); + MTL_STRINGISE_ENUM(TextureType2DMultisample); + MTL_STRINGISE_ENUM(TextureTypeCube); + MTL_STRINGISE_ENUM(TextureTypeCubeArray); + MTL_STRINGISE_ENUM(TextureType3D); + MTL_STRINGISE_ENUM(TextureType2DMultisampleArray); + MTL_STRINGISE_ENUM(TextureTypeTextureBuffer); + } + END_ENUM_STRINGISE() +} + +template <> +rdcstr DoStringise(const MTL::TextureUsage &el) +{ + BEGIN_BITFIELD_STRINGISE(MTL::TextureUsage) + { + MTL_STRINGISE_BITFIELD_VALUE(TextureUsageUnknown); + MTL_STRINGISE_BITFIELD_BIT(TextureUsageShaderRead); + MTL_STRINGISE_BITFIELD_BIT(TextureUsageShaderWrite); + MTL_STRINGISE_BITFIELD_BIT(TextureUsageRenderTarget); + MTL_STRINGISE_BITFIELD_BIT(TextureUsagePixelFormatView); + } + END_BITFIELD_STRINGISE() +} + +template <> +rdcstr DoStringise(const MTL::TextureSwizzle &el) +{ + BEGIN_ENUM_STRINGISE(MTL::TextureSwizzle) + { + MTL_STRINGISE_ENUM(TextureSwizzleZero); + MTL_STRINGISE_ENUM(TextureSwizzleOne); + MTL_STRINGISE_ENUM(TextureSwizzleRed); + MTL_STRINGISE_ENUM(TextureSwizzleGreen); + MTL_STRINGISE_ENUM(TextureSwizzleBlue); + MTL_STRINGISE_ENUM(TextureSwizzleAlpha); + } + END_ENUM_STRINGISE() +} + +template <> +rdcstr DoStringise(const MTL::BlendFactor &el) +{ + BEGIN_ENUM_STRINGISE(MTL::BlendFactor) + { + MTL_STRINGISE_ENUM(BlendFactorZero); + MTL_STRINGISE_ENUM(BlendFactorOne); + MTL_STRINGISE_ENUM(BlendFactorSourceColor); + MTL_STRINGISE_ENUM(BlendFactorOneMinusSourceColor); + MTL_STRINGISE_ENUM(BlendFactorSourceAlpha); + MTL_STRINGISE_ENUM(BlendFactorOneMinusSourceAlpha); + MTL_STRINGISE_ENUM(BlendFactorDestinationColor); + MTL_STRINGISE_ENUM(BlendFactorOneMinusDestinationColor); + MTL_STRINGISE_ENUM(BlendFactorDestinationAlpha); + MTL_STRINGISE_ENUM(BlendFactorOneMinusDestinationAlpha); + MTL_STRINGISE_ENUM(BlendFactorSourceAlphaSaturated); + MTL_STRINGISE_ENUM(BlendFactorBlendColor); + MTL_STRINGISE_ENUM(BlendFactorOneMinusBlendColor); + MTL_STRINGISE_ENUM(BlendFactorBlendAlpha); + MTL_STRINGISE_ENUM(BlendFactorOneMinusBlendAlpha); + MTL_STRINGISE_ENUM(BlendFactorSource1Color); + MTL_STRINGISE_ENUM(BlendFactorOneMinusSource1Color); + MTL_STRINGISE_ENUM(BlendFactorSource1Alpha); + MTL_STRINGISE_ENUM(BlendFactorOneMinusSource1Alpha); + } + END_ENUM_STRINGISE() +} + +template <> +rdcstr DoStringise(const MTL::BlendOperation &el) +{ + BEGIN_ENUM_STRINGISE(MTL::BlendOperation) + { + MTL_STRINGISE_ENUM(BlendOperationAdd); + MTL_STRINGISE_ENUM(BlendOperationSubtract); + MTL_STRINGISE_ENUM(BlendOperationReverseSubtract); + MTL_STRINGISE_ENUM(BlendOperationMin); + MTL_STRINGISE_ENUM(BlendOperationMax); + } + END_ENUM_STRINGISE() +} + +template <> +rdcstr DoStringise(const MTL::ColorWriteMask &el) +{ + BEGIN_BITFIELD_STRINGISE(MTL::ColorWriteMask) + { + MTL_STRINGISE_BITFIELD_VALUE(ColorWriteMaskNone); + MTL_STRINGISE_BITFIELD_VALUE(ColorWriteMaskAll); + MTL_STRINGISE_BITFIELD_BIT(ColorWriteMaskAlpha); + MTL_STRINGISE_BITFIELD_BIT(ColorWriteMaskBlue); + MTL_STRINGISE_BITFIELD_BIT(ColorWriteMaskGreen); + MTL_STRINGISE_BITFIELD_BIT(ColorWriteMaskRed); + } + END_BITFIELD_STRINGISE() +} diff --git a/renderdoc/driver/metal/metal_texture.cpp b/renderdoc/driver/metal/metal_texture.cpp new file mode 100644 index 000000000..9ce076094 --- /dev/null +++ b/renderdoc/driver/metal/metal_texture.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_texture.h" +#include "metal_device.h" + +WrappedMTLTexture::WrappedMTLTexture(MTL::Texture *realMTLTexture, ResourceId objId, + WrappedMTLDevice *wrappedMTLDevice) + : WrappedMTLObject(realMTLTexture, objId, wrappedMTLDevice, wrappedMTLDevice->GetStateRef()) +{ + AllocateObjCBridge(this); +} diff --git a/renderdoc/driver/metal/metal_texture.h b/renderdoc/driver/metal/metal_texture.h new file mode 100644 index 000000000..4ac99f53b --- /dev/null +++ b/renderdoc/driver/metal/metal_texture.h @@ -0,0 +1,41 @@ +/****************************************************************************** + * 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 WrappedMTLTexture : public WrappedMTLObject +{ +public: + WrappedMTLTexture(MTL::Texture *realMTLTexture, ResourceId objId, + WrappedMTLDevice *wrappedMTLDevice); + + enum + { + TypeEnum = eResTexture + }; + +private: +}; diff --git a/renderdoc/driver/metal/metal_texture_bridge.mm b/renderdoc/driver/metal/metal_texture_bridge.mm new file mode 100644 index 000000000..8e7c49944 --- /dev/null +++ b/renderdoc/driver/metal/metal_texture_bridge.mm @@ -0,0 +1,371 @@ +/****************************************************************************** + * 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_texture.h" +#include "metal_types_bridge.h" + +// Bridge for MTLTexture +@implementation ObjCBridgeMTLTexture + +// ObjCBridgeMTLTexture specific +- (id)real +{ + return id(Unwrap(GetWrapped(self))); +} + +// Silence compiler warning +// error: method possibly missing a [super dealloc] call [-Werror,-Wobjc-missing-super-calls] +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-missing-super-calls" +- (void)dealloc +{ + GetWrapped(self)->Dealloc(); +} +#pragma clang diagnostic pop + +// Use the real MTLTexture to find methods from messages +- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector +{ + id fwd = self.real; + return [fwd methodSignatureForSelector:aSelector]; +} + +// Forward any unknown messages to the real MTLTexture +- (void)forwardInvocation:(NSInvocation *)invocation +{ + SEL aSelector = [invocation selector]; + + if([self.real respondsToSelector:aSelector]) + [invocation invokeWithTarget:self.real]; + else + [super forwardInvocation:invocation]; +} + +// MTLResource : based on the protocol defined in +// Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Metal.framework/Headers/MTLResource.h + +- (nullable NSString *)label +{ + return self.real.label; +} + +- (void)setLabel:value +{ + self.real.label = value; +} + +- (id)device +{ + return id(GetWrapped(self)->GetDevice()); +} + +- (MTLCPUCacheMode)cpuCacheMode +{ + return self.real.cpuCacheMode; +} + +- (MTLStorageMode)storageMode API_AVAILABLE(macos(10.11), ios(9.0)) +{ + return self.real.storageMode; +} + +- (MTLHazardTrackingMode)hazardTrackingMode API_AVAILABLE(macos(10.15), ios(13.0)) +{ + return self.real.hazardTrackingMode; +} + +- (MTLResourceOptions)resourceOptions API_AVAILABLE(macos(10.15), ios(13.0)) +{ + return self.real.resourceOptions; +} + +- (MTLPurgeableState)setPurgeableState:(MTLPurgeableState)state +{ + METAL_NOT_HOOKED(); + return [self.real setPurgeableState:state]; +} + +- (id)heap API_AVAILABLE(macos(10.13), ios(10.0)) +{ + return self.real.heap; +} + +- (NSUInteger)heapOffset API_AVAILABLE(macos(10.15), ios(13.0)) +{ + return self.real.heapOffset; +} + +- (NSUInteger)allocatedSize API_AVAILABLE(macos(10.13), ios(11.0)) +{ + return self.real.allocatedSize; +} + +- (void)makeAliasable API_AVAILABLE(macos(10.13), ios(10.0)) +{ + METAL_NOT_HOOKED(); + return [self.real makeAliasable]; +} + +- (BOOL)isAliasable API_AVAILABLE(macos(10.13), ios(10.0)) +{ + return [self.real isAliasable]; +} + +// MTLTexture : based on the protocol defined in +// Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Metal.framework/Headers/MTLTexture.h + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-implementations" +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +- (id)rootResource + API_DEPRECATED("Use parentTexture or buffer instead", macos(10.11, 10.12), ios(8.0, 10.0)) +{ + return self.real.rootResource; +} +#pragma clang diagnostic pop + +- (id)parentTexture API_AVAILABLE(macos(10.11), ios(9.0)) +{ + return self.real.parentTexture; +} + +- (NSUInteger)parentRelativeLevel API_AVAILABLE(macos(10.11), ios(9.0)) +{ + return self.real.parentRelativeLevel; +} + +- (NSUInteger)parentRelativeSlice API_AVAILABLE(macos(10.11), ios(9.0)) +{ + return self.real.parentRelativeSlice; +} + +- (id)buffer API_AVAILABLE(macos(10.12), ios(9.0)) +{ + return self.real.buffer; +} + +- (NSUInteger)bufferOffset API_AVAILABLE(macos(10.12), ios(9.0)) +{ + return self.real.bufferOffset; +} + +- (NSUInteger)bufferBytesPerRow API_AVAILABLE(macos(10.12), ios(9.0)) +{ + return self.real.bufferBytesPerRow; +} + +- (IOSurfaceRef)iosurface API_AVAILABLE(macos(10.11), ios(11.0)) +{ + return self.real.iosurface; +} + +- (NSUInteger)iosurfacePlane API_AVAILABLE(macos(10.11), ios(11.0)) +{ + return self.real.iosurfacePlane; +} + +- (MTLTextureType)textureType +{ + return self.real.textureType; +} + +- (MTLPixelFormat)pixelFormat +{ + return self.real.pixelFormat; +} + +- (NSUInteger)width +{ + return self.real.width; +} + +- (NSUInteger)height +{ + return self.real.height; +} + +- (NSUInteger)depth +{ + return self.real.depth; +} + +- (NSUInteger)mipmapLevelCount +{ + return self.real.mipmapLevelCount; +} + +- (NSUInteger)sampleCount +{ + return self.real.sampleCount; +} + +- (NSUInteger)arrayLength +{ + return self.real.arrayLength; +} + +- (MTLTextureUsage)usage +{ + return self.real.usage; +} + +- (BOOL)isShareable API_AVAILABLE(macos(10.14), ios(13.0)) +{ + return self.real.isShareable; +} + +- (BOOL)isFramebufferOnly +{ + return self.real.isFramebufferOnly; +} + +- (NSUInteger)firstMipmapInTail API_AVAILABLE(macos(11.0), macCatalyst(14.0), ios(13.0)) +{ + return self.real.firstMipmapInTail; +} + +- (NSUInteger)tailSizeInBytes API_AVAILABLE(macos(11.0), macCatalyst(14.0), ios(13.0)) +{ + return self.real.tailSizeInBytes; +} + +- (BOOL)isSparse API_AVAILABLE(macos(11.0), macCatalyst(14.0), ios(13.0)) +{ + return self.real.isSparse; +} + +- (BOOL)allowGPUOptimizedContents API_AVAILABLE(macos(10.14), ios(12.0)) +{ + return self.real.allowGPUOptimizedContents; +} + +- (void)getBytes:(void *)pixelBytes + bytesPerRow:(NSUInteger)bytesPerRow + bytesPerImage:(NSUInteger)bytesPerImage + fromRegion:(MTLRegion)region + mipmapLevel:(NSUInteger)level + slice:(NSUInteger)slice +{ + METAL_NOT_HOOKED(); + [self.real getBytes:pixelBytes + bytesPerRow:bytesPerRow + bytesPerImage:bytesPerImage + fromRegion:region + mipmapLevel:level + slice:slice]; +} + +- (void)replaceRegion:(MTLRegion)region + mipmapLevel:(NSUInteger)level + slice:(NSUInteger)slice + withBytes:(const void *)pixelBytes + bytesPerRow:(NSUInteger)bytesPerRow + bytesPerImage:(NSUInteger)bytesPerImage +{ + METAL_NOT_HOOKED(); + [self.real replaceRegion:region + mipmapLevel:level + slice:slice + withBytes:pixelBytes + bytesPerRow:bytesPerRow + bytesPerImage:bytesPerImage]; +} + +- (void)getBytes:(void *)pixelBytes + bytesPerRow:(NSUInteger)bytesPerRow + fromRegion:(MTLRegion)region + mipmapLevel:(NSUInteger)level +{ + METAL_NOT_HOOKED(); + [self.real getBytes:pixelBytes bytesPerRow:bytesPerRow fromRegion:region mipmapLevel:level]; +} + +- (void)replaceRegion:(MTLRegion)region + mipmapLevel:(NSUInteger)level + withBytes:(const void *)pixelBytes + bytesPerRow:(NSUInteger)bytesPerRow +{ + METAL_NOT_HOOKED(); + [self.real replaceRegion:region mipmapLevel:level withBytes:pixelBytes bytesPerRow:bytesPerRow]; +} + +- (nullable id)newTextureViewWithPixelFormat:(MTLPixelFormat)pixelFormat +{ + METAL_NOT_HOOKED(); + return [self.real newTextureViewWithPixelFormat:pixelFormat]; +} + +- (nullable id)newTextureViewWithPixelFormat:(MTLPixelFormat)pixelFormat + textureType:(MTLTextureType)textureType + levels:(NSRange)levelRange + slices:(NSRange)sliceRange + API_AVAILABLE(macos(10.11), ios(9.0)) +{ + METAL_NOT_HOOKED(); + return [self.real newTextureViewWithPixelFormat:pixelFormat + textureType:textureType + levels:levelRange + slices:sliceRange]; +} + +- (nullable MTLSharedTextureHandle *)newSharedTextureHandle API_AVAILABLE(macos(10.14), ios(13.0)) +{ + METAL_NOT_HOOKED(); + return [self.real newSharedTextureHandle]; +} + +- (id)remoteStorageTexture API_AVAILABLE(macos(10.15))API_UNAVAILABLE(ios) +{ + METAL_NOT_HOOKED(); + return [self.real remoteStorageTexture]; +} + +- (nullable id)newRemoteTextureViewForDevice:(id)device + API_AVAILABLE(macos(10.15))API_UNAVAILABLE(ios) +{ + METAL_NOT_HOOKED(); + return [self.real newRemoteTextureViewForDevice:device]; +} + +- (MTLTextureSwizzleChannels)swizzle API_AVAILABLE(macos(10.15), ios(13.0)) +{ + return self.real.swizzle; +} + +- (nullable id)newTextureViewWithPixelFormat:(MTLPixelFormat)pixelFormat + textureType:(MTLTextureType)textureType + levels:(NSRange)levelRange + slices:(NSRange)sliceRange + swizzle:(MTLTextureSwizzleChannels)swizzle + API_AVAILABLE(macos(10.15), ios(13.0)) +{ + METAL_NOT_HOOKED(); + return [self.real newTextureViewWithPixelFormat:pixelFormat + textureType:textureType + levels:levelRange + slices:sliceRange + swizzle:swizzle]; +} + +@end diff --git a/renderdoc/driver/metal/metal_types.cpp b/renderdoc/driver/metal/metal_types.cpp index 502a98dca..e5620ab06 100644 --- a/renderdoc/driver/metal/metal_types.cpp +++ b/renderdoc/driver/metal/metal_types.cpp @@ -29,7 +29,9 @@ #include "metal_function.h" #include "metal_library.h" #include "metal_manager.h" +#include "metal_render_pipeline_state.h" #include "metal_resources.h" +#include "metal_texture.h" RDCCOMPILE_ASSERT(sizeof(NS::Integer) == sizeof(std::intptr_t), "NS::Integer size does not match"); RDCCOMPILE_ASSERT(sizeof(NS::UInteger) == sizeof(std::uintptr_t), @@ -121,4 +123,499 @@ void DoSerialise(SerialiserType &ser, NS::String *&el) } } +template +void DoSerialise(SerialiserType &ser, MTL::TextureSwizzleChannels &el) +{ + SERIALISE_MEMBER(red); + SERIALISE_MEMBER(green); + SERIALISE_MEMBER(blue); + SERIALISE_MEMBER(alpha); +} + +template +void DoSerialise(SerialiserType &ser, RDMTL::TextureDescriptor &el) +{ + SERIALISE_MEMBER(textureType); + SERIALISE_MEMBER(pixelFormat); + SERIALISE_MEMBER(width); + SERIALISE_MEMBER(height); + SERIALISE_MEMBER(depth); + SERIALISE_MEMBER(mipmapLevelCount); + SERIALISE_MEMBER(sampleCount); + SERIALISE_MEMBER(arrayLength); + SERIALISE_MEMBER(resourceOptions); + SERIALISE_MEMBER(cpuCacheMode); + SERIALISE_MEMBER(storageMode); + SERIALISE_MEMBER(hazardTrackingMode); + SERIALISE_MEMBER(usage); + SERIALISE_MEMBER(allowGPUOptimizedContents); + SERIALISE_MEMBER(swizzle); +} + +template +void DoSerialise(SerialiserType &ser, RDMTL::RenderPipelineColorAttachmentDescriptor &el) +{ + SERIALISE_MEMBER(pixelFormat); + SERIALISE_MEMBER(blendingEnabled); + SERIALISE_MEMBER(sourceRGBBlendFactor); + SERIALISE_MEMBER(destinationRGBBlendFactor); + SERIALISE_MEMBER(rgbBlendOperation); + SERIALISE_MEMBER(sourceAlphaBlendFactor); + SERIALISE_MEMBER(destinationAlphaBlendFactor); + SERIALISE_MEMBER(alphaBlendOperation); + SERIALISE_MEMBER(writeMask); +} + +template +void DoSerialise(SerialiserType &ser, RDMTL::PipelineBufferDescriptor &el) +{ + SERIALISE_MEMBER(mutability); +} + +template +void DoSerialise(SerialiserType &ser, RDMTL::VertexAttributeDescriptor &el) +{ + SERIALISE_MEMBER(format); + SERIALISE_MEMBER(offset); + SERIALISE_MEMBER(bufferIndex); +} + +template +void DoSerialise(SerialiserType &ser, RDMTL::VertexBufferLayoutDescriptor &el) +{ + SERIALISE_MEMBER(stride); + SERIALISE_MEMBER(stepFunction); + SERIALISE_MEMBER(stepRate); +} + +template +void DoSerialise(SerialiserType &ser, RDMTL::VertexDescriptor &el) +{ + SERIALISE_MEMBER(layouts); + SERIALISE_MEMBER(attributes); +} + +template +void DoSerialise(SerialiserType &ser, RDMTL::FunctionGroups &el) +{ + SERIALISE_MEMBER(callsite); + SERIALISE_MEMBER(functions); +} + +template +void DoSerialise(SerialiserType &ser, RDMTL::LinkedFunctions &el) +{ + SERIALISE_MEMBER(functions); + SERIALISE_MEMBER(binaryFunctions); + SERIALISE_MEMBER(groups); + SERIALISE_MEMBER(privateFunctions); +} + +template +void DoSerialise(SerialiserType &ser, RDMTL::RenderPipelineDescriptor &el) +{ + SERIALISE_MEMBER(label); + SERIALISE_MEMBER(vertexFunction); + SERIALISE_MEMBER(fragmentFunction); + SERIALISE_MEMBER(vertexDescriptor); + SERIALISE_MEMBER(sampleCount); + SERIALISE_MEMBER(rasterSampleCount); + SERIALISE_MEMBER(alphaToCoverageEnabled); + SERIALISE_MEMBER(alphaToOneEnabled); + SERIALISE_MEMBER(rasterizationEnabled); + SERIALISE_MEMBER(maxVertexAmplificationCount); + SERIALISE_MEMBER(colorAttachments); + SERIALISE_MEMBER(depthAttachmentPixelFormat); + SERIALISE_MEMBER(stencilAttachmentPixelFormat); + SERIALISE_MEMBER(inputPrimitiveTopology); + SERIALISE_MEMBER(tessellationPartitionMode); + SERIALISE_MEMBER(maxTessellationFactor); + SERIALISE_MEMBER(tessellationFactorScaleEnabled); + SERIALISE_MEMBER(tessellationFactorFormat); + SERIALISE_MEMBER(tessellationControlPointIndexType); + SERIALISE_MEMBER(tessellationFactorStepFunction); + SERIALISE_MEMBER(tessellationOutputWindingOrder); + SERIALISE_MEMBER(vertexBuffers); + SERIALISE_MEMBER(fragmentBuffers); + SERIALISE_MEMBER(supportIndirectCommandBuffers); + // TODO: will MTL::BinaryArchive need to be a wrapped resource + // SERIALISE_MEMBER(binaryArchives); + // TODO: will MTL::DynamicLibrary need to be a wrapped resource + // SERIALISE_MEMBER(vertexPreloadedLibraries); + // SERIALISE_MEMBER(fragmentPreloadedLibraries); + SERIALISE_MEMBER(vertexLinkedFunctions); + SERIALISE_MEMBER(fragmentLinkedFunctions); + SERIALISE_MEMBER(supportAddingVertexBinaryFunctions); + SERIALISE_MEMBER(supportAddingFragmentBinaryFunctions); + SERIALISE_MEMBER(maxVertexCallStackDepth); + SERIALISE_MEMBER(maxFragmentCallStackDepth); +} + +static bool ValidData(MTL::VertexAttributeDescriptor *attribute) +{ + if(attribute->format() == MTL::VertexFormatInvalid) + return false; + return true; +} + +static bool ValidData(MTL::VertexBufferLayoutDescriptor *layout) +{ + if(layout->stride() == 0) + return false; + return true; +} + +static bool ValidData(MTL::PipelineBufferDescriptor *descriptor) +{ + if(descriptor->mutability() == MTL::MutabilityDefault) + return false; + return true; +} + +static bool ValidData(MTL::RenderPipelineColorAttachmentDescriptor *descriptor) +{ + if(descriptor->pixelFormat() == MTL::PixelFormatInvalid) + return false; + return true; +} + +namespace RDMTL +{ +template +static void GetWrappedNSArray(rdcarray::Outer *> &to, NS::Array *from) +{ + int count = from->count(); + to.resize(count); + for(int i = 0; i < count; ++i) + { + to[i] = GetWrapped((MTL_TYPE)from->object(i)); + } +} + +#define GETWRAPPEDNSARRAY(TYPE, NAME) GetWrappedNSArray(NAME, objc->NAME()) + +template +static NS::Array *CreateUnwrappedNSArray(rdcarray::Outer *> &from) +{ + int count = from.count(); + if(count) + { + rdcarray unwrapped(count); + for(int i = 0; i < count; ++i) + { + unwrapped[i] = Unwrap(from[i]); + } + return NS::Array::array((NS::Object **)(unwrapped.data()), unwrapped.count()); + } + return NULL; +} + +template +static void GetObjcArray(rdcarray &to, MTLARRAY_TYPE *from, bool (*validData)(MTL_TYPE *)) +{ + MTL_TYPE *objcData[MAX_COUNT]; + int count = 0; + for(int i = 0; i < MAX_COUNT; ++i) + { + objcData[i] = from->object(i); + if(objcData[i] && validData(objcData[i])) + { + count = i + 1; + } + } + if(count) + { + to.resize(count); + for(int i = 0; i < count; ++i) + { + if(objcData[i] && validData(objcData[i])) + { + to[i] = RDMTL_TYPE(objcData[i]); + } + } + } +} + +#define GETOBJCARRAY(TYPE, COUNT, NAME, VALIDDATA_FUNC) \ + GetObjcArray(NAME, objc->NAME(), VALIDDATA_FUNC) + +template +static void CopyToObjcArray(MTLARRAY_TYPE *to, rdcarray &from) +{ + for(int i = 0; i < from.count(); ++i) + { + from[i].CopyTo(to->object(i)); + } +} + +#define COPYTOOBJCARRAY(TYPE, NAME) \ + CopyToObjcArray(objc->NAME(), NAME) + +TextureDescriptor::TextureDescriptor(MTL::TextureDescriptor *objc) +{ + textureType = objc->textureType(); + pixelFormat = objc->pixelFormat(); + width = objc->width(); + height = objc->height(); + depth = objc->depth(); + mipmapLevelCount = objc->mipmapLevelCount(); + sampleCount = objc->sampleCount(); + arrayLength = objc->arrayLength(); + resourceOptions = objc->resourceOptions(); + cpuCacheMode = objc->cpuCacheMode(); + storageMode = objc->storageMode(); + hazardTrackingMode = objc->hazardTrackingMode(); + usage = objc->usage(); + allowGPUOptimizedContents = objc->allowGPUOptimizedContents(); + swizzle = objc->swizzle(); +} + +TextureDescriptor::operator MTL::TextureDescriptor *() +{ + MTL::TextureDescriptor *objc = MTL::TextureDescriptor::alloc()->init(); + objc->setTextureType(textureType); + objc->setPixelFormat(pixelFormat); + objc->setWidth(width); + objc->setHeight(height); + objc->setDepth(depth); + objc->setMipmapLevelCount(mipmapLevelCount); + objc->setSampleCount(sampleCount); + objc->setArrayLength(arrayLength); + objc->setResourceOptions(resourceOptions); + objc->setCpuCacheMode(cpuCacheMode); + objc->setStorageMode(storageMode); + objc->setHazardTrackingMode(hazardTrackingMode); + objc->setUsage(usage); + objc->setAllowGPUOptimizedContents(allowGPUOptimizedContents); + objc->setSwizzle(swizzle); + return objc; +} + +RenderPipelineColorAttachmentDescriptor::RenderPipelineColorAttachmentDescriptor( + MTL::RenderPipelineColorAttachmentDescriptor *objc) + : pixelFormat(objc->pixelFormat()), + blendingEnabled(objc->blendingEnabled()), + sourceRGBBlendFactor(objc->sourceAlphaBlendFactor()), + destinationRGBBlendFactor(objc->destinationRGBBlendFactor()), + rgbBlendOperation(objc->rgbBlendOperation()), + sourceAlphaBlendFactor(objc->sourceAlphaBlendFactor()), + destinationAlphaBlendFactor(objc->destinationAlphaBlendFactor()), + alphaBlendOperation(objc->alphaBlendOperation()), + writeMask(objc->writeMask()) +{ +} + +void RenderPipelineColorAttachmentDescriptor::CopyTo(MTL::RenderPipelineColorAttachmentDescriptor *objc) +{ + objc->setPixelFormat(pixelFormat); + objc->setBlendingEnabled(blendingEnabled); + objc->setSourceRGBBlendFactor(sourceRGBBlendFactor); + objc->setDestinationRGBBlendFactor(destinationRGBBlendFactor); + objc->setRgbBlendOperation(rgbBlendOperation); + objc->setSourceAlphaBlendFactor(sourceAlphaBlendFactor); + objc->setDestinationAlphaBlendFactor(destinationAlphaBlendFactor); + objc->setAlphaBlendOperation(alphaBlendOperation); + objc->setWriteMask(writeMask); +} + +PipelineBufferDescriptor::PipelineBufferDescriptor(MTL::PipelineBufferDescriptor *objc) + : mutability(objc->mutability()) +{ +} + +void PipelineBufferDescriptor::CopyTo(MTL::PipelineBufferDescriptor *objc) +{ + objc->setMutability(mutability); +} + +VertexAttributeDescriptor::VertexAttributeDescriptor(MTL::VertexAttributeDescriptor *objc) + : format(objc->format()), offset(objc->offset()), bufferIndex(objc->bufferIndex()) +{ +} + +void VertexAttributeDescriptor::CopyTo(MTL::VertexAttributeDescriptor *objc) +{ + objc->setFormat(format); + objc->setOffset(offset); + objc->setBufferIndex(bufferIndex); +} + +VertexBufferLayoutDescriptor::VertexBufferLayoutDescriptor(MTL::VertexBufferLayoutDescriptor *objc) + : stride(objc->stride()), stepFunction(objc->stepFunction()), stepRate(objc->stepRate()) +{ +} + +void VertexBufferLayoutDescriptor::CopyTo(MTL::VertexBufferLayoutDescriptor *objc) +{ + objc->setStride(stride); + objc->setStepFunction(stepFunction); + objc->setStepRate(stepRate); +} + +VertexDescriptor::VertexDescriptor(MTL::VertexDescriptor *objc) +{ + GETOBJCARRAY(VertexBufferLayoutDescriptor, MAX_VERTEX_SHADER_ATTRIBUTES, layouts, ValidData); + GETOBJCARRAY(VertexAttributeDescriptor, MAX_VERTEX_SHADER_ATTRIBUTES, attributes, ValidData); +} + +void VertexDescriptor::CopyTo(MTL::VertexDescriptor *objc) +{ + COPYTOOBJCARRAY(VertexBufferLayoutDescriptor, layouts); + COPYTOOBJCARRAY(VertexAttributeDescriptor, attributes); +} + +LinkedFunctions::LinkedFunctions(MTL::LinkedFunctions *objc) +{ + GETWRAPPEDNSARRAY(Function, functions); + GETWRAPPEDNSARRAY(Function, binaryFunctions); + { + NS::Dictionary *objcGroups = objc->groups(); + NS::Array *keys = objcGroups->keyEnumerator()->allObjects(); + int countKeys = keys->count(); + + groups.resize(countKeys); + for(int i = 0; i < countKeys; ++i) + { + NS::String *key = (NS::String *)keys->object(i); + NS::Array *funcs = (NS::Array *)objcGroups->object(key); + int countFuncs = funcs->count(); + + FunctionGroups &funcGroup = groups[i]; + funcGroup.callsite.assign(key->utf8String()); + funcGroup.functions.resize(countFuncs); + for(int j = 0; j < countFuncs; ++j) + { + funcGroup.functions[j] = GetWrapped((MTL::Function *)funcs->object(j)); + } + } + } + GETWRAPPEDNSARRAY(Function, privateFunctions); +} + +void LinkedFunctions::CopyTo(MTL::LinkedFunctions *objc) +{ + objc->setFunctions(CreateUnwrappedNSArray(functions)); + objc->setBinaryFunctions(CreateUnwrappedNSArray(binaryFunctions)); + { + NS::Dictionary *inGroups = NULL; + int countKeys = groups.count(); + if(countKeys) + { + rdcarray values(countKeys); + rdcarray keys(countKeys); + for(int i = 0; i < countKeys; ++i) + { + FunctionGroups &funcGroup = groups[i]; + keys[i] = NS::String::string(funcGroup.callsite.data(), NS::UTF8StringEncoding); + values[i] = CreateUnwrappedNSArray(funcGroup.functions); + } + + inGroups = NS::Dictionary::dictionary((NS::Object **)values.data(), + (NS::Object **)keys.data(), countKeys); + } + objc->setGroups(inGroups); + } + objc->setPrivateFunctions(CreateUnwrappedNSArray(privateFunctions)); +} + +RenderPipelineDescriptor::RenderPipelineDescriptor(MTL::RenderPipelineDescriptor *objc) + : vertexFunction(GetWrapped(objc->vertexFunction())), + fragmentFunction(GetWrapped(objc->fragmentFunction())), + vertexDescriptor(objc->vertexDescriptor()), + sampleCount(objc->sampleCount()), + rasterSampleCount(objc->rasterSampleCount()), + alphaToCoverageEnabled(objc->alphaToCoverageEnabled()), + alphaToOneEnabled(objc->alphaToOneEnabled()), + rasterizationEnabled(objc->rasterizationEnabled()), + maxVertexAmplificationCount(objc->maxVertexAmplificationCount()), + depthAttachmentPixelFormat(objc->depthAttachmentPixelFormat()), + stencilAttachmentPixelFormat(objc->stencilAttachmentPixelFormat()), + inputPrimitiveTopology(objc->inputPrimitiveTopology()), + tessellationPartitionMode(objc->tessellationPartitionMode()), + maxTessellationFactor(objc->maxTessellationFactor()), + tessellationFactorScaleEnabled(objc->tessellationFactorScaleEnabled()), + tessellationFactorFormat(objc->tessellationFactorFormat()), + tessellationControlPointIndexType(objc->tessellationControlPointIndexType()), + tessellationFactorStepFunction(objc->tessellationFactorStepFunction()), + tessellationOutputWindingOrder(objc->tessellationOutputWindingOrder()), + supportIndirectCommandBuffers(objc->supportIndirectCommandBuffers()), + vertexLinkedFunctions(objc->vertexLinkedFunctions()), + fragmentLinkedFunctions(objc->fragmentLinkedFunctions()), + supportAddingVertexBinaryFunctions(objc->supportAddingVertexBinaryFunctions()), + supportAddingFragmentBinaryFunctions(objc->supportAddingFragmentBinaryFunctions()), + maxVertexCallStackDepth(objc->maxVertexCallStackDepth()), + maxFragmentCallStackDepth(objc->maxFragmentCallStackDepth()) +{ + if(objc->label()) + label.assign(objc->label()->utf8String()); + GETOBJCARRAY(RenderPipelineColorAttachmentDescriptor, MAX_RENDER_PASS_COLOR_ATTACHMENTS, + colorAttachments, ValidData); + GETOBJCARRAY(PipelineBufferDescriptor, MAX_RENDER_PASS_BUFFER_ATTACHMENTS, vertexBuffers, + ValidData); + GETOBJCARRAY(PipelineBufferDescriptor, MAX_RENDER_PASS_BUFFER_ATTACHMENTS, fragmentBuffers, + ValidData); + // TODO: will MTL::BinaryArchive need to be a wrapped resource + // rdcarray binaryArchives; + // TODO: will MTL::DynamicLibrary need to be a wrapped resource + // rdcarray vertexPreloadedLibraries; + // rdcarray fragmentPreloadedLibraries; +} + +RenderPipelineDescriptor::operator MTL::RenderPipelineDescriptor *() +{ + MTL::RenderPipelineDescriptor *objc = MTL::RenderPipelineDescriptor::alloc()->init(); + if(label.length() > 0) + { + objc->setLabel(NS::String::string(label.data(), NS::UTF8StringEncoding)); + } + objc->setVertexFunction(Unwrap(vertexFunction)); + objc->setFragmentFunction(Unwrap(fragmentFunction)); + vertexDescriptor.CopyTo(objc->vertexDescriptor()); + objc->setSampleCount(sampleCount); + objc->setRasterSampleCount(rasterSampleCount); + objc->setAlphaToCoverageEnabled(alphaToCoverageEnabled); + objc->setAlphaToOneEnabled(alphaToOneEnabled); + objc->setRasterizationEnabled(rasterizationEnabled); + objc->setMaxVertexAmplificationCount(maxVertexAmplificationCount); + COPYTOOBJCARRAY(RenderPipelineColorAttachmentDescriptor, colorAttachments); + objc->setDepthAttachmentPixelFormat(depthAttachmentPixelFormat); + objc->setStencilAttachmentPixelFormat(stencilAttachmentPixelFormat); + objc->setInputPrimitiveTopology(inputPrimitiveTopology); + objc->setTessellationPartitionMode(tessellationPartitionMode); + objc->setMaxTessellationFactor(maxTessellationFactor); + objc->setTessellationFactorScaleEnabled(tessellationFactorScaleEnabled); + objc->setTessellationFactorFormat(tessellationFactorFormat); + objc->setTessellationControlPointIndexType(tessellationControlPointIndexType); + objc->setTessellationFactorStepFunction(tessellationFactorStepFunction); + objc->setTessellationOutputWindingOrder(tessellationOutputWindingOrder); + COPYTOOBJCARRAY(PipelineBufferDescriptor, vertexBuffers); + COPYTOOBJCARRAY(PipelineBufferDescriptor, fragmentBuffers); + objc->setSupportIndirectCommandBuffers(supportIndirectCommandBuffers); + // TODO: will MTL::BinaryArchive need to be a wrapped resource + // rdcarray binaryArchives; + // TODO: will MTL::DynamicLibrary need to be a wrapped resource + // rdcarray vertexPreloadedLibraries; + // rdcarray fragmentPreloadedLibraries; + vertexLinkedFunctions.CopyTo(objc->vertexLinkedFunctions()); + fragmentLinkedFunctions.CopyTo(objc->fragmentLinkedFunctions()); + objc->setSupportAddingVertexBinaryFunctions(supportAddingVertexBinaryFunctions); + objc->setSupportAddingFragmentBinaryFunctions(supportAddingFragmentBinaryFunctions); + objc->setMaxVertexCallStackDepth(maxVertexCallStackDepth); + objc->setMaxFragmentCallStackDepth(maxFragmentCallStackDepth); + + return objc; +} + +} // namespace RDMTL + INSTANTIATE_SERIALISE_TYPE(NS::String *); +INSTANTIATE_SERIALISE_TYPE(MTL::TextureSwizzleChannels); +INSTANTIATE_SERIALISE_TYPE(RDMTL::TextureDescriptor); +INSTANTIATE_SERIALISE_TYPE(RDMTL::RenderPipelineColorAttachmentDescriptor); +INSTANTIATE_SERIALISE_TYPE(RDMTL::PipelineBufferDescriptor); +INSTANTIATE_SERIALISE_TYPE(RDMTL::VertexAttributeDescriptor); +INSTANTIATE_SERIALISE_TYPE(RDMTL::VertexBufferLayoutDescriptor); +INSTANTIATE_SERIALISE_TYPE(RDMTL::VertexDescriptor); +INSTANTIATE_SERIALISE_TYPE(RDMTL::FunctionGroups); +INSTANTIATE_SERIALISE_TYPE(RDMTL::LinkedFunctions); +INSTANTIATE_SERIALISE_TYPE(RDMTL::RenderPipelineDescriptor); diff --git a/renderdoc/driver/metal/metal_types.h b/renderdoc/driver/metal/metal_types.h index bac33ef46..c7bf2a583 100644 --- a/renderdoc/driver/metal/metal_types.h +++ b/renderdoc/driver/metal/metal_types.h @@ -28,12 +28,19 @@ #include "official/metal-cpp.h" #include "serialise/serialiser.h" +// TODO: use Metal Feature sets to determine these values at capture time +const uint32_t MAX_RENDER_PASS_COLOR_ATTACHMENTS = 8; +const uint32_t MAX_RENDER_PASS_BUFFER_ATTACHMENTS = 31; +const uint32_t MAX_VERTEX_SHADER_ATTRIBUTES = 31; + #define METALCPP_WRAPPED_PROTOCOLS(FUNC) \ FUNC(CommandBuffer); \ FUNC(CommandQueue); \ FUNC(Device); \ FUNC(Function); \ - FUNC(Library); + FUNC(Library); \ + FUNC(RenderPipelineState); \ + FUNC(Texture); // These serialise overloads will fetch the ID during capture, serialise the ID // directly as-if it were the original type, then on replay load up the resource if available. @@ -61,6 +68,191 @@ METALCPP_WRAPPED_PROTOCOLS(DECLARE_WRAPPED_TYPE_SERIALISE); METALCPP_WRAPPED_PROTOCOLS(DECLARE_OBJC_HELPERS) #undef DECLARE_OBJC_HELPERS +#define MTL_DECLARE_REFLECTION_TYPE(TYPE) \ + template <> \ + inline rdcliteral TypeName() \ + { \ + return STRING_LITERAL(STRINGIZE(MTL##TYPE)); \ + } \ + template \ + void DoSerialise(SerialiserType &ser, MTL::TYPE &el); + +MTL_DECLARE_REFLECTION_TYPE(TextureType); +MTL_DECLARE_REFLECTION_TYPE(PixelFormat); +MTL_DECLARE_REFLECTION_TYPE(ResourceOptions); +MTL_DECLARE_REFLECTION_TYPE(CPUCacheMode); +MTL_DECLARE_REFLECTION_TYPE(StorageMode); +MTL_DECLARE_REFLECTION_TYPE(HazardTrackingMode); +MTL_DECLARE_REFLECTION_TYPE(TextureUsage); +MTL_DECLARE_REFLECTION_TYPE(TextureSwizzleChannels); +MTL_DECLARE_REFLECTION_TYPE(TextureSwizzle); +MTL_DECLARE_REFLECTION_TYPE(BlendFactor); +MTL_DECLARE_REFLECTION_TYPE(BlendOperation); +MTL_DECLARE_REFLECTION_TYPE(ColorWriteMask); +MTL_DECLARE_REFLECTION_TYPE(Mutability); +MTL_DECLARE_REFLECTION_TYPE(VertexFormat); +MTL_DECLARE_REFLECTION_TYPE(VertexStepFunction); +MTL_DECLARE_REFLECTION_TYPE(PrimitiveTopologyClass); +MTL_DECLARE_REFLECTION_TYPE(TessellationPartitionMode); +MTL_DECLARE_REFLECTION_TYPE(TessellationFactorFormat); +MTL_DECLARE_REFLECTION_TYPE(TessellationControlPointIndexType); +MTL_DECLARE_REFLECTION_TYPE(TessellationFactorStepFunction); +MTL_DECLARE_REFLECTION_TYPE(Winding); + +namespace RDMTL +{ +// MTLTextureDescriptor : based on the interface defined in +// Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Metal.framework/Headers/MTLTexture.h +struct TextureDescriptor +{ + TextureDescriptor() = default; + TextureDescriptor(MTL::TextureDescriptor *objc); + explicit operator MTL::TextureDescriptor *(); + MTL::TextureType textureType; + MTL::PixelFormat pixelFormat; + NS::UInteger width; + NS::UInteger height; + NS::UInteger depth; + NS::UInteger mipmapLevelCount; + NS::UInteger sampleCount; + NS::UInteger arrayLength; + MTL::ResourceOptions resourceOptions; + MTL::CPUCacheMode cpuCacheMode; + MTL::StorageMode storageMode; + MTL::HazardTrackingMode hazardTrackingMode; + MTL::TextureUsage usage; + bool allowGPUOptimizedContents; + MTL::TextureSwizzleChannels swizzle; +}; + +// MTLRenderPipelineColorAttachmentDescriptor : based on the interface defined in +// Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Metal.framework/Headers/MTLRenderPipeline.h +struct RenderPipelineColorAttachmentDescriptor +{ + RenderPipelineColorAttachmentDescriptor() = default; + RenderPipelineColorAttachmentDescriptor(MTL::RenderPipelineColorAttachmentDescriptor *objc); + void CopyTo(MTL::RenderPipelineColorAttachmentDescriptor *objc); + MTL::PixelFormat pixelFormat; + bool blendingEnabled; + MTL::BlendFactor sourceRGBBlendFactor; + MTL::BlendFactor destinationRGBBlendFactor; + MTL::BlendOperation rgbBlendOperation; + MTL::BlendFactor sourceAlphaBlendFactor; + MTL::BlendFactor destinationAlphaBlendFactor; + MTL::BlendOperation alphaBlendOperation; + MTL::ColorWriteMask writeMask; +}; + +// MTLPipelineBufferDescriptor : based on the interface defined in +// Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Metal.framework/Headers/MTLPipeline.h +struct PipelineBufferDescriptor +{ + PipelineBufferDescriptor() = default; + PipelineBufferDescriptor(MTL::PipelineBufferDescriptor *objc); + void CopyTo(MTL::PipelineBufferDescriptor *objc); + MTL::Mutability mutability; +}; + +// MTLVertexAttributeDescriptor : based on the interface defined in +// Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Metal.framework/Headers/MTLVertexDescriptor.h +struct VertexAttributeDescriptor +{ + VertexAttributeDescriptor() = default; + VertexAttributeDescriptor(MTL::VertexAttributeDescriptor *objc); + void CopyTo(MTL::VertexAttributeDescriptor *objc); + MTL::VertexFormat format; + NS::UInteger offset; + NS::UInteger bufferIndex; +}; + +// MTLVertexBufferLayoutDescriptor : based on the interface defined in +// Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Metal.framework/Headers/MTLVertexDescriptor.h +struct VertexBufferLayoutDescriptor +{ + VertexBufferLayoutDescriptor() = default; + VertexBufferLayoutDescriptor(MTL::VertexBufferLayoutDescriptor *objc); + void CopyTo(MTL::VertexBufferLayoutDescriptor *objc); + NS::UInteger stride; + MTL::VertexStepFunction stepFunction; + NS::UInteger stepRate; +}; + +// MTLVertexBufferLayoutDescriptor : based on the interface defined in +// Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Metal.framework/Headers/MTLVertexDescriptor.h +struct VertexDescriptor +{ + VertexDescriptor() = default; + VertexDescriptor(MTL::VertexDescriptor *objc); + void CopyTo(MTL::VertexDescriptor *objc); + rdcarray layouts; + rdcarray attributes; +}; + +struct FunctionGroups +{ + rdcstr callsite; + rdcarray functions; +}; + +// MTLLinkedFunctions : based on the interface defined in +// Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Metal.framework/Headers/MTLLinkedFunctions.h +struct LinkedFunctions +{ + LinkedFunctions() = default; + LinkedFunctions(MTL::LinkedFunctions *objc); + void CopyTo(MTL::LinkedFunctions *objc); + rdcarray functions; + rdcarray binaryFunctions; + rdcarray groups; + rdcarray privateFunctions; +}; + +// MTLRenderPipelineDescriptor : based on the interface defined in +// Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Metal.framework/Headers/MTLRenderPipeline.h +struct RenderPipelineDescriptor +{ + RenderPipelineDescriptor() = default; + RenderPipelineDescriptor(MTL::RenderPipelineDescriptor *objc); + explicit operator MTL::RenderPipelineDescriptor *(); + rdcstr label; + WrappedMTLFunction *vertexFunction; + WrappedMTLFunction *fragmentFunction; + VertexDescriptor vertexDescriptor; + NS::UInteger sampleCount; + NS::UInteger rasterSampleCount; + bool alphaToCoverageEnabled; + bool alphaToOneEnabled; + bool rasterizationEnabled; + NS::UInteger maxVertexAmplificationCount; + rdcarray colorAttachments; + MTL::PixelFormat depthAttachmentPixelFormat; + MTL::PixelFormat stencilAttachmentPixelFormat; + MTL::PrimitiveTopologyClass inputPrimitiveTopology; + MTL::TessellationPartitionMode tessellationPartitionMode; + NS::UInteger maxTessellationFactor; + bool tessellationFactorScaleEnabled; + MTL::TessellationFactorFormat tessellationFactorFormat; + MTL::TessellationControlPointIndexType tessellationControlPointIndexType; + MTL::TessellationFactorStepFunction tessellationFactorStepFunction; + MTL::Winding tessellationOutputWindingOrder; + rdcarray vertexBuffers; + rdcarray fragmentBuffers; + bool supportIndirectCommandBuffers; + // TODO: will MTL::BinaryArchive need to be a wrapped resource + // rdcarray binaryArchives; + // TODO: will MTL::DynamicLibrary need to be a wrapped resource + // rdcarray vertexPreloadedLibraries; + // rdcarray fragmentPreloadedLibraries; + LinkedFunctions vertexLinkedFunctions; + LinkedFunctions fragmentLinkedFunctions; + bool supportAddingVertexBinaryFunctions; + bool supportAddingFragmentBinaryFunctions; + NS::UInteger maxVertexCallStackDepth; + NS::UInteger maxFragmentCallStackDepth; +}; + +} // namespace RDMTL + template <> inline rdcliteral TypeName() { @@ -68,3 +260,13 @@ inline rdcliteral TypeName() } template void DoSerialise(SerialiserType &ser, NS::String *&el); + +DECLARE_REFLECTION_STRUCT(RDMTL::TextureDescriptor); +DECLARE_REFLECTION_STRUCT(RDMTL::RenderPipelineColorAttachmentDescriptor); +DECLARE_REFLECTION_STRUCT(RDMTL::PipelineBufferDescriptor); +DECLARE_REFLECTION_STRUCT(RDMTL::VertexAttributeDescriptor); +DECLARE_REFLECTION_STRUCT(RDMTL::VertexBufferLayoutDescriptor); +DECLARE_REFLECTION_STRUCT(RDMTL::VertexDescriptor); +DECLARE_REFLECTION_STRUCT(RDMTL::FunctionGroups); +DECLARE_REFLECTION_STRUCT(RDMTL::LinkedFunctions); +DECLARE_REFLECTION_STRUCT(RDMTL::RenderPipelineDescriptor);