From 22b227281221000dbac71aee83d710c7f7ccee24 Mon Sep 17 00:00:00 2001 From: Jake Turner Date: Tue, 22 Mar 2022 21:40:56 +0000 Subject: [PATCH] Added wrapped MTLBuffer --- renderdoc/driver/metal/CMakeLists.txt | 3 + renderdoc/driver/metal/metal_buffer.cpp | 116 +++++++++++ renderdoc/driver/metal/metal_buffer.h | 46 +++++ renderdoc/driver/metal/metal_buffer_bridge.mm | 189 ++++++++++++++++++ renderdoc/driver/metal/metal_common.h | 9 + renderdoc/driver/metal/metal_device.cpp | 71 +++++++ renderdoc/driver/metal/metal_device.h | 5 + renderdoc/driver/metal/metal_device_bridge.mm | 7 +- .../metal/metal_render_command_encoder.cpp | 93 +++++++++ .../metal/metal_render_command_encoder.h | 4 + .../metal_render_command_encoder_bridge.mm | 6 +- renderdoc/driver/metal/metal_resources.cpp | 1 + renderdoc/driver/metal/metal_resources.h | 1 + renderdoc/driver/metal/metal_serialise.cpp | 12 +- renderdoc/driver/metal/metal_types.cpp | 7 +- renderdoc/driver/metal/metal_types.h | 12 +- 16 files changed, 566 insertions(+), 16 deletions(-) create mode 100644 renderdoc/driver/metal/metal_buffer.cpp create mode 100644 renderdoc/driver/metal/metal_buffer.h create mode 100644 renderdoc/driver/metal/metal_buffer_bridge.mm diff --git a/renderdoc/driver/metal/CMakeLists.txt b/renderdoc/driver/metal/CMakeLists.txt index a5cce8fe0..17df343cc 100644 --- a/renderdoc/driver/metal/CMakeLists.txt +++ b/renderdoc/driver/metal/CMakeLists.txt @@ -31,6 +31,9 @@ set(sources metal_texture.cpp metal_texture.h metal_texture_bridge.mm + metal_buffer.cpp + metal_buffer.h + metal_buffer_bridge.mm metal_render_command_encoder.cpp metal_render_command_encoder.h metal_render_command_encoder_bridge.mm diff --git a/renderdoc/driver/metal/metal_buffer.cpp b/renderdoc/driver/metal/metal_buffer.cpp new file mode 100644 index 000000000..d8504af34 --- /dev/null +++ b/renderdoc/driver/metal/metal_buffer.cpp @@ -0,0 +1,116 @@ +/****************************************************************************** + * 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_buffer.h" +#include "core/core.h" +#include "metal_resources.h" + +WrappedMTLBuffer::WrappedMTLBuffer(MTL::Buffer *realMTLBuffer, ResourceId objId, + WrappedMTLDevice *wrappedMTLDevice) + : WrappedMTLObject(realMTLBuffer, objId, wrappedMTLDevice, wrappedMTLDevice->GetStateRef()) +{ + AllocateObjCBridge(this); +} + +void *WrappedMTLBuffer::contents() +{ + void *data = Unwrap(this)->contents(); + + if(IsCaptureMode(m_State)) + { + // Snapshot potentially CPU modified buffer if the returned pointer is not NULL + if(data) + { + GetResourceManager()->MarkDirtyResource(m_ID); + } + } + else + { + // TODO: implement RD MTL replay + } + return data; +} + +template +bool WrappedMTLBuffer::Serialise_didModifyRange(SerialiserType &ser, NS::Range &range) +{ + SERIALISE_ELEMENT_LOCAL(Buffer, this); + SERIALISE_ELEMENT(range).Important(); + byte *pData = NULL; + uint64_t memSize = range.length; + if(ser.IsWriting()) + { + pData = (byte *)Unwrap(this)->contents() + range.location; + } + if(IsReplayingAndReading()) + { + pData = (byte *)Unwrap(Buffer)->contents() + range.location; + } + + // serialise directly using buffer memory + ser.Serialise("data"_lit, pData, memSize, SerialiserFlags::NoFlags).Important(); + + SERIALISE_CHECK_READ_ERRORS(); + + // TODO: implement RD MTL replay + if(IsReplayingAndReading()) + { + Unwrap(Buffer)->didModifyRange(range); + } + return true; +} + +void WrappedMTLBuffer::didModifyRange(NS::Range &range) +{ + SERIALISE_TIME_CALL(Unwrap(this)->didModifyRange(range)); + if(IsCaptureMode(m_State)) + { + bool backframe = IsBackgroundCapturing(m_State); + if(backframe) + { + // Snapshot potentially CPU modified buffer + GetResourceManager()->MarkDirtyResource(m_ID); + } + + bool capframe = IsActiveCapturing(m_State); + if(capframe) + { + Chunk *chunk = NULL; + { + CACHE_THREAD_SERIALISER(); + SCOPED_SERIALISE_CHUNK(MetalChunk::MTLBuffer_didModifyRange); + Serialise_didModifyRange(ser, range); + chunk = scope.Get(); + } + // TODO: add to the frame capture record chunk + // m_Device->AddFrameCaptureRecordChunk(chunk); + } + } + else + { + // TODO: implement RD MTL replay + } +} + +INSTANTIATE_FUNCTION_SERIALISED(WrappedMTLBuffer, void, didModifyRange, NS::Range &); diff --git a/renderdoc/driver/metal/metal_buffer.h b/renderdoc/driver/metal/metal_buffer.h new file mode 100644 index 000000000..49251b0c7 --- /dev/null +++ b/renderdoc/driver/metal/metal_buffer.h @@ -0,0 +1,46 @@ +/****************************************************************************** + * 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" +#include "metal_device.h" +#include "metal_resources.h" + +class WrappedMTLBuffer : public WrappedMTLObject +{ +public: + WrappedMTLBuffer(MTL::Buffer *realMTLBuffer, ResourceId objId, WrappedMTLDevice *wrappedMTLDevice); + + void *contents(); + + DECLARE_FUNCTION_SERIALISED(void, didModifyRange, NS::Range &range); + + enum + { + TypeEnum = eResBuffer + }; + +private: +}; diff --git a/renderdoc/driver/metal/metal_buffer_bridge.mm b/renderdoc/driver/metal/metal_buffer_bridge.mm new file mode 100644 index 000000000..9ca4024ae --- /dev/null +++ b/renderdoc/driver/metal/metal_buffer_bridge.mm @@ -0,0 +1,189 @@ +/****************************************************************************** + * 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_buffer.h" +#include "metal_types_bridge.h" + +// Bridge for MTLBuffer +@implementation ObjCBridgeMTLBuffer + +// ObjCBridgeMTLBuffer 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 MTLBuffer to find methods from messages +- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector +{ + id fwd = self.real; + return [fwd methodSignatureForSelector:aSelector]; +} + +// Forward any unknown messages to the real MTLBuffer +- (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]; +} + +// MTLBuffer : based on the protocol defined in +// Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Metal.framework/Headers/MTLBuffer.h + +- (NSUInteger)length +{ + return self.real.length; +} + +- (void *)contents NS_RETURNS_INNER_POINTER +{ + return GetWrapped(self)->contents(); +} + +- (void)didModifyRange:(NSRange)range API_AVAILABLE(macos(10.11), macCatalyst(13.0)) + API_UNAVAILABLE(ios) +{ + return GetWrapped(self)->didModifyRange((NS::Range &)range); +} + +- (nullable id)newTextureWithDescriptor:(MTLTextureDescriptor *)descriptor + offset:(NSUInteger)offset + bytesPerRow:(NSUInteger)bytesPerRow + API_AVAILABLE(macos(10.13), ios(8.0)) +{ + METAL_NOT_HOOKED(); + return [self.real newTextureWithDescriptor:descriptor offset:offset bytesPerRow:bytesPerRow]; +} + +- (void)addDebugMarker:(NSString *)marker + range:(NSRange)range API_AVAILABLE(macos(10.12), ios(10.0)) +{ + METAL_NOT_HOOKED(); + return [self.real addDebugMarker:marker range:range]; +} + +- (void)removeAllDebugMarkers API_AVAILABLE(macos(10.12), ios(10.0)) +{ + METAL_NOT_HOOKED(); + return [self.real removeAllDebugMarkers]; +} + +- (id)remoteStorageBuffer API_AVAILABLE(macos(10.15))API_UNAVAILABLE(ios) +{ + // TODO: This should be the wrapped MTLBuffer + return self.real.remoteStorageBuffer; +} + +- (nullable id)newRemoteBufferViewForDevice:(id)device + API_AVAILABLE(macos(10.15))API_UNAVAILABLE(ios) +{ + METAL_NOT_HOOKED(); + return [self.real newRemoteBufferViewForDevice:device]; +} + +@end diff --git a/renderdoc/driver/metal/metal_common.h b/renderdoc/driver/metal/metal_common.h index 16a8d738a..3493b0e9e 100644 --- a/renderdoc/driver/metal/metal_common.h +++ b/renderdoc/driver/metal/metal_common.h @@ -223,6 +223,15 @@ enum class MetalChunk : uint32_t MTLRenderCommandEncoder_memoryBarrierWithScope, MTLRenderCommandEncoder_memoryBarrierWithResources, MTLRenderCommandEncoder_sampleCountersInBuffer, + MTLBuffer_setPurgeableState, + MTLBuffer_makeAliasable, + MTLBuffer_contents, + MTLBuffer_didModifyRange, + MTLBuffer_newTextureWithDescriptor, + MTLBuffer_addDebugMarker, + MTLBuffer_removeAllDebugMarkers, + MTLBuffer_remoteStorageBuffer, + MTLBuffer_newRemoteBufferViewForDevice, Max }; diff --git a/renderdoc/driver/metal/metal_device.cpp b/renderdoc/driver/metal/metal_device.cpp index 2f676b307..9dbe121e6 100644 --- a/renderdoc/driver/metal/metal_device.cpp +++ b/renderdoc/driver/metal/metal_device.cpp @@ -23,6 +23,7 @@ ******************************************************************************/ #include "metal_device.h" +#include "metal_buffer.h" #include "metal_command_queue.h" #include "metal_function.h" #include "metal_helpers_bridge.h" @@ -238,6 +239,42 @@ WrappedMTLLibrary *WrappedMTLDevice::newLibraryWithSource(NS::String *source, return wrappedMTLLibrary; } +template +bool WrappedMTLDevice::Serialise_newBufferWithBytes(SerialiserType &ser, WrappedMTLBuffer *buffer, + const void *pointer, NS::UInteger length, + MTL::ResourceOptions options) +{ + SERIALISE_ELEMENT_LOCAL(Buffer, GetResID(buffer)).TypedAs("MTLBuffer"_lit); + bytebuf initialData; + if(pointer) + { + initialData.assign((byte *)pointer, length); + } + SERIALISE_ELEMENT(initialData); + SERIALISE_ELEMENT(length).Important(); + SERIALISE_ELEMENT(options); + + SERIALISE_CHECK_READ_ERRORS(); + + // TODO: implement RD MTL replay + if(IsReplayingAndReading()) + { + } + return true; +} + +WrappedMTLBuffer *WrappedMTLDevice::newBufferWithBytes(const void *pointer, NS::UInteger length, + MTL::ResourceOptions options) +{ + return Common_NewBuffer(true, pointer, length, options); +} + +WrappedMTLBuffer *WrappedMTLDevice::newBufferWithLength(NS::UInteger length, + MTL::ResourceOptions options) +{ + return Common_NewBuffer(false, NULL, length, options); +} + template bool WrappedMTLDevice::Serialise_newRenderPipelineStateWithDescriptor( SerialiserType &ser, WrappedMTLRenderPipelineState *pipelineState, @@ -501,6 +538,37 @@ WrappedMTLTexture *WrappedMTLDevice::Common_NewTexture(RDMTL::TextureDescriptor return wrappedMTLTexture; } +WrappedMTLBuffer *WrappedMTLDevice::Common_NewBuffer(bool withBytes, const void *pointer, + NS::UInteger length, + MTL::ResourceOptions options) +{ + MTL::Buffer *realMTLBuffer; + SERIALISE_TIME_CALL(realMTLBuffer = withBytes ? Unwrap(this)->newBuffer(pointer, length, options) + : Unwrap(this)->newBuffer(length, options)); + + WrappedMTLBuffer *wrappedMTLBuffer; + ResourceId id = GetResourceManager()->WrapResource(realMTLBuffer, wrappedMTLBuffer); + if(IsCaptureMode(m_State)) + { + Chunk *chunk = NULL; + { + CACHE_THREAD_SERIALISER(); + SCOPED_SERIALISE_CHUNK(withBytes ? MetalChunk::MTLDevice_newBufferWithBytes + : MetalChunk::MTLDevice_newBufferWithLength); + Serialise_newBufferWithBytes(ser, wrappedMTLBuffer, pointer, length, options); + chunk = scope.Get(); + } + + MetalResourceRecord *record = GetResourceManager()->AddResourceRecord(wrappedMTLBuffer); + record->AddChunk(chunk); + } + else + { + // TODO: implement RD MTL replay + } + return wrappedMTLBuffer; +} + INSTANTIATE_FUNCTION_WITH_RETURN_SERIALISED(WrappedMTLDevice, WrappedMTLCommandQueue *, newCommandQueue); INSTANTIATE_FUNCTION_WITH_RETURN_SERIALISED(WrappedMTLDevice, WrappedMTLLibrary *, newDefaultLibrary); @@ -515,3 +583,6 @@ INSTANTIATE_FUNCTION_WITH_RETURN_SERIALISED(WrappedMTLDevice, INSTANTIATE_FUNCTION_WITH_RETURN_SERIALISED(WrappedMTLDevice, WrappedMTLTexture *, newTextureWithDescriptor, RDMTL::TextureDescriptor &descriptor); +INSTANTIATE_FUNCTION_WITH_RETURN_SERIALISED(WrappedMTLDevice, WrappedMTLBuffer *, + newBufferWithBytes, const void *pointer, + NS::UInteger length, MTL::ResourceOptions options); diff --git a/renderdoc/driver/metal/metal_device.h b/renderdoc/driver/metal/metal_device.h index dbbeabb8b..66036a657 100644 --- a/renderdoc/driver/metal/metal_device.h +++ b/renderdoc/driver/metal/metal_device.h @@ -50,6 +50,9 @@ public: IOSurfaceRef iosurface, NS::UInteger plane); DECLARE_FUNCTION_WITH_RETURN_SERIALISED(WrappedMTLTexture *, newTextureWithDescriptor, RDMTL::TextureDescriptor &descriptor); + WrappedMTLBuffer *newBufferWithLength(NS::UInteger length, MTL::ResourceOptions options); + DECLARE_FUNCTION_WITH_RETURN_SERIALISED(WrappedMTLBuffer *, newBufferWithBytes, const void *pointer, + NS::UInteger length, MTL::ResourceOptions options); // Non-Serialised MTLDevice APIs bool isDepth24Stencil8PixelFormatSupported(); @@ -106,6 +109,8 @@ private: WrappedMTLTexture *Common_NewTexture(RDMTL::TextureDescriptor &descriptor, MetalChunk chunkType, bool ioSurfaceTexture, IOSurfaceRef iosurface, NS::UInteger plane); + WrappedMTLBuffer *Common_NewBuffer(bool withBytes, const void *pointer, NS::UInteger length, + MTL::ResourceOptions options); MetalResourceManager *m_ResourceManager; diff --git a/renderdoc/driver/metal/metal_device_bridge.mm b/renderdoc/driver/metal/metal_device_bridge.mm index e9c569f93..12bfd246f 100644 --- a/renderdoc/driver/metal/metal_device_bridge.mm +++ b/renderdoc/driver/metal/metal_device_bridge.mm @@ -223,16 +223,15 @@ - (nullable id)newBufferWithLength:(NSUInteger)length options:(MTLResourceOptions)options { - METAL_NOT_HOOKED(); - return [self.real newBufferWithLength:length options:options]; + return id(GetWrapped(self)->newBufferWithLength(length, (MTL::ResourceOptions)options)); } - (nullable id)newBufferWithBytes:(const void *)pointer length:(NSUInteger)length options:(MTLResourceOptions)options { - METAL_NOT_HOOKED(); - return [self.real newBufferWithBytes:pointer length:length options:options]; + return id( + GetWrapped(self)->newBufferWithBytes(pointer, length, (MTL::ResourceOptions)options)); } - (nullable id)newBufferWithBytesNoCopy:(void *)pointer diff --git a/renderdoc/driver/metal/metal_render_command_encoder.cpp b/renderdoc/driver/metal/metal_render_command_encoder.cpp index 8b92b9eec..204ec24c7 100644 --- a/renderdoc/driver/metal/metal_render_command_encoder.cpp +++ b/renderdoc/driver/metal/metal_render_command_encoder.cpp @@ -23,6 +23,7 @@ ******************************************************************************/ #include "metal_render_command_encoder.h" +#include "metal_buffer.h" #include "metal_command_buffer.h" #include "metal_manager.h" #include "metal_render_pipeline_state.h" @@ -76,6 +77,94 @@ void WrappedMTLRenderCommandEncoder::setRenderPipelineState(WrappedMTLRenderPipe } } +template +bool WrappedMTLRenderCommandEncoder::Serialise_setVertexBuffer(SerialiserType &ser, + WrappedMTLBuffer *buffer, + NS::UInteger offset, + NS::UInteger index) +{ + SERIALISE_ELEMENT_LOCAL(RenderCommandEncoder, this); + SERIALISE_ELEMENT(buffer).Important(); + SERIALISE_ELEMENT(offset); + SERIALISE_ELEMENT(index).Important(); + + SERIALISE_CHECK_READ_ERRORS(); + + // TODO: implement RD MTL replay + if(IsReplayingAndReading()) + { + } + return true; +} + +void WrappedMTLRenderCommandEncoder::setVertexBuffer(WrappedMTLBuffer *buffer, NS::UInteger offset, + NS::UInteger index) +{ + SERIALISE_TIME_CALL(Unwrap(this)->setVertexBuffer(Unwrap(buffer), offset, index)); + + if(IsCaptureMode(m_State)) + { + Chunk *chunk = NULL; + { + CACHE_THREAD_SERIALISER(); + SCOPED_SERIALISE_CHUNK(MetalChunk::MTLRenderCommandEncoder_setVertexBuffer); + Serialise_setVertexBuffer(ser, buffer, offset, index); + chunk = scope.Get(); + } + MetalResourceRecord *bufferRecord = GetRecord(m_CommandBuffer); + bufferRecord->AddChunk(chunk); + bufferRecord->MarkResourceFrameReferenced(GetResID(buffer), eFrameRef_Read); + } + else + { + // TODO: implement RD MTL replay + } +} + +template +bool WrappedMTLRenderCommandEncoder::Serialise_setFragmentBuffer(SerialiserType &ser, + WrappedMTLBuffer *buffer, + NS::UInteger offset, + NS::UInteger index) +{ + SERIALISE_ELEMENT_LOCAL(RenderCommandEncoder, this); + SERIALISE_ELEMENT(buffer).Important(); + SERIALISE_ELEMENT(offset); + SERIALISE_ELEMENT(index).Important(); + + SERIALISE_CHECK_READ_ERRORS(); + + // TODO: implement RD MTL replay + if(IsReplayingAndReading()) + { + } + return true; +} + +void WrappedMTLRenderCommandEncoder::setFragmentBuffer(WrappedMTLBuffer *buffer, + NS::UInteger offset, NS::UInteger index) +{ + SERIALISE_TIME_CALL(Unwrap(this)->setFragmentBuffer(Unwrap(buffer), offset, index)); + + if(IsCaptureMode(m_State)) + { + Chunk *chunk = NULL; + { + CACHE_THREAD_SERIALISER(); + SCOPED_SERIALISE_CHUNK(MetalChunk::MTLRenderCommandEncoder_setFragmentBuffer); + Serialise_setFragmentBuffer(ser, buffer, offset, index); + chunk = scope.Get(); + } + MetalResourceRecord *bufferRecord = GetRecord(m_CommandBuffer); + bufferRecord->AddChunk(chunk); + bufferRecord->MarkResourceFrameReferenced(GetResID(buffer), eFrameRef_Read); + } + else + { + // TODO: implement RD MTL replay + } +} + template bool WrappedMTLRenderCommandEncoder::Serialise_setFragmentTexture(SerialiserType &ser, WrappedMTLTexture *texture, @@ -258,6 +347,10 @@ void WrappedMTLRenderCommandEncoder::endEncoding() INSTANTIATE_FUNCTION_SERIALISED(WrappedMTLRenderCommandEncoder, void, endEncoding); INSTANTIATE_FUNCTION_SERIALISED(WrappedMTLRenderCommandEncoder, void, setRenderPipelineState, WrappedMTLRenderPipelineState *pipelineState); +INSTANTIATE_FUNCTION_SERIALISED(WrappedMTLRenderCommandEncoder, void, setVertexBuffer, + WrappedMTLBuffer *buffer, NS::UInteger offset, NS::UInteger index); +INSTANTIATE_FUNCTION_SERIALISED(WrappedMTLRenderCommandEncoder, void, setFragmentBuffer, + WrappedMTLBuffer *buffer, NS::UInteger offset, NS::UInteger index); INSTANTIATE_FUNCTION_SERIALISED(WrappedMTLRenderCommandEncoder, void, setFragmentTexture, WrappedMTLTexture *texture, NS::UInteger index); INSTANTIATE_FUNCTION_SERIALISED(WrappedMTLRenderCommandEncoder, void, setViewport, diff --git a/renderdoc/driver/metal/metal_render_command_encoder.h b/renderdoc/driver/metal/metal_render_command_encoder.h index d7f7677a2..28da6f416 100644 --- a/renderdoc/driver/metal/metal_render_command_encoder.h +++ b/renderdoc/driver/metal/metal_render_command_encoder.h @@ -37,6 +37,10 @@ public: void SetCommandBuffer(WrappedMTLCommandBuffer *commandBuffer) { m_CommandBuffer = commandBuffer; } DECLARE_FUNCTION_SERIALISED(void, setRenderPipelineState, WrappedMTLRenderPipelineState *pipelineState); + DECLARE_FUNCTION_SERIALISED(void, setVertexBuffer, WrappedMTLBuffer *buffer, NS::UInteger offset, + NS::UInteger index); + DECLARE_FUNCTION_SERIALISED(void, setFragmentBuffer, WrappedMTLBuffer *buffer, + NS::UInteger offset, NS::UInteger index); DECLARE_FUNCTION_SERIALISED(void, setFragmentTexture, WrappedMTLTexture *texture, NS::UInteger index); DECLARE_FUNCTION_SERIALISED(void, setViewport, MTL::Viewport &viewport); diff --git a/renderdoc/driver/metal/metal_render_command_encoder_bridge.mm b/renderdoc/driver/metal/metal_render_command_encoder_bridge.mm index 1bc99272b..ea49d2030 100644 --- a/renderdoc/driver/metal/metal_render_command_encoder_bridge.mm +++ b/renderdoc/driver/metal/metal_render_command_encoder_bridge.mm @@ -123,8 +123,7 @@ offset:(NSUInteger)offset atIndex:(NSUInteger)index { - METAL_NOT_HOOKED(); - return [self.real setVertexBuffer:buffer offset:offset atIndex:index]; + GetWrapped(self)->setVertexBuffer(GetWrapped(buffer), offset, index); } - (void)setVertexBufferOffset:(NSUInteger)offset @@ -318,8 +317,7 @@ offset:(NSUInteger)offset atIndex:(NSUInteger)index { - METAL_NOT_HOOKED(); - [self.real setFragmentBuffer:buffer offset:offset atIndex:index]; + GetWrapped(self)->setFragmentBuffer(GetWrapped(buffer), offset, index); } - (void)setFragmentBufferOffset:(NSUInteger)offset diff --git a/renderdoc/driver/metal/metal_resources.cpp b/renderdoc/driver/metal/metal_resources.cpp index 8a4c71cbc..3c5571f4e 100644 --- a/renderdoc/driver/metal/metal_resources.cpp +++ b/renderdoc/driver/metal/metal_resources.cpp @@ -23,6 +23,7 @@ ******************************************************************************/ #include "metal_resources.h" +#include "metal_buffer.h" #include "metal_command_buffer.h" #include "metal_command_queue.h" #include "metal_device.h" diff --git a/renderdoc/driver/metal/metal_resources.h b/renderdoc/driver/metal/metal_resources.h index ca9096fb0..2db69db4a 100644 --- a/renderdoc/driver/metal/metal_resources.h +++ b/renderdoc/driver/metal/metal_resources.h @@ -35,6 +35,7 @@ class MetalResourceManager; enum MetalResourceType { eResUnknown = 0, + eResBuffer, eResCommandBuffer, eResCommandQueue, eResDevice, diff --git a/renderdoc/driver/metal/metal_serialise.cpp b/renderdoc/driver/metal/metal_serialise.cpp index e0dd78833..755e22cb5 100644 --- a/renderdoc/driver/metal/metal_serialise.cpp +++ b/renderdoc/driver/metal/metal_serialise.cpp @@ -22,6 +22,7 @@ * THE SOFTWARE. ******************************************************************************/ +#include "metal_buffer.h" #include "metal_command_buffer.h" #include "metal_command_queue.h" #include "metal_device.h" @@ -94,6 +95,13 @@ void DoSerialise(SerialiserType &ser, NS::String *&el) } } +template +void DoSerialise(SerialiserType &ser, NS::Range &el) +{ + SERIALISE_MEMBER(location); + SERIALISE_MEMBER(length); +} + template void DoSerialise(SerialiserType &ser, MTL::TextureSwizzleChannels &el) { @@ -305,8 +313,7 @@ void DoSerialise(SerialiserType &ser, RDMTL::RenderPassDescriptor &el) SERIALISE_MEMBER(colorAttachments); SERIALISE_MEMBER(depthAttachment); SERIALISE_MEMBER(stencilAttachment); - // TODO: when WrappedMTLBuffer exists - // WrappedMTLBuffer *visibilityResultBuffer; + SERIALISE_MEMBER(visibilityResultBuffer); SERIALISE_MEMBER(renderTargetArrayLength); SERIALISE_MEMBER(imageblockSampleLength); SERIALISE_MEMBER(threadgroupMemoryLength); @@ -322,6 +329,7 @@ void DoSerialise(SerialiserType &ser, RDMTL::RenderPassDescriptor &el) }; INSTANTIATE_SERIALISE_TYPE(NS::String *); +INSTANTIATE_SERIALISE_TYPE(NS::Range) INSTANTIATE_SERIALISE_TYPE(MTL::TextureSwizzleChannels); INSTANTIATE_SERIALISE_TYPE(MTL::ClearColor); INSTANTIATE_SERIALISE_TYPE(MTL::SamplePosition); diff --git a/renderdoc/driver/metal/metal_types.cpp b/renderdoc/driver/metal/metal_types.cpp index a21fff023..c7c20b319 100644 --- a/renderdoc/driver/metal/metal_types.cpp +++ b/renderdoc/driver/metal/metal_types.cpp @@ -23,6 +23,7 @@ ******************************************************************************/ #include "metal_types.h" +#include "metal_buffer.h" #include "metal_command_buffer.h" #include "metal_command_queue.h" #include "metal_device.h" @@ -520,8 +521,7 @@ void RenderPassSampleBufferAttachmentDescriptor::CopyTo( RenderPassDescriptor::RenderPassDescriptor(MTL::RenderPassDescriptor *objc) : depthAttachment(objc->depthAttachment()), stencilAttachment(objc->stencilAttachment()), - // TODO: when WrappedMTLBuffer exists - // visibilityResultBuffer(GetWrapped(objc->visibilityResultBuffer())), + visibilityResultBuffer(GetWrapped(objc->visibilityResultBuffer())), renderTargetArrayLength(objc->renderTargetArrayLength()), imageblockSampleLength(objc->imageblockSampleLength()), threadgroupMemoryLength(objc->threadgroupMemoryLength()), @@ -551,8 +551,7 @@ RenderPassDescriptor::operator MTL::RenderPassDescriptor *() COPYTOOBJCARRAY(RenderPassColorAttachmentDescriptor, colorAttachments); depthAttachment.CopyTo(objc->depthAttachment()); stencilAttachment.CopyTo(objc->stencilAttachment()); - // TODO: when WrappedMTLBuffer exists - // objc->setVisibilityResultBuffer(Unwrap(visibilityResultBuffer)); + objc->setVisibilityResultBuffer(Unwrap(visibilityResultBuffer)); objc->setRenderTargetArrayLength(renderTargetArrayLength); objc->setImageblockSampleLength(imageblockSampleLength); objc->setThreadgroupMemoryLength(threadgroupMemoryLength); diff --git a/renderdoc/driver/metal/metal_types.h b/renderdoc/driver/metal/metal_types.h index d0f1afc47..5aa4f582a 100644 --- a/renderdoc/driver/metal/metal_types.h +++ b/renderdoc/driver/metal/metal_types.h @@ -40,6 +40,7 @@ const uint32_t MAX_RENDER_PASS_SAMPLE_BUFFER_ATTACHMENTS = 4; #endif // #ifndef MTLCounterDontSample #define METALCPP_WRAPPED_PROTOCOLS(FUNC) \ + FUNC(Buffer); \ FUNC(CommandBuffer); \ FUNC(CommandQueue); \ FUNC(Device); \ @@ -115,6 +116,14 @@ MTL_DECLARE_REFLECTION_TYPE(MultisampleDepthResolveFilter); MTL_DECLARE_REFLECTION_TYPE(MultisampleStencilResolveFilter); MTL_DECLARE_REFLECTION_TYPE(SamplePosition); +template <> +inline rdcliteral TypeName() +{ + return "NSRange"_lit; +} +template +void DoSerialise(SerialiserType &ser, NS::Range &el); + namespace RDMTL { // MTLTextureDescriptor : based on the interface defined in @@ -358,8 +367,7 @@ struct RenderPassDescriptor rdcarray colorAttachments; RenderPassDepthAttachmentDescriptor depthAttachment; RenderPassStencilAttachmentDescriptor stencilAttachment; - // TODO: when WrappedMTLBuffer exists - // WrappedMTLBuffer *visibilityResultBuffer; + WrappedMTLBuffer *visibilityResultBuffer = NULL; NS::UInteger renderTargetArrayLength = 0; NS::UInteger imageblockSampleLength = 0; NS::UInteger threadgroupMemoryLength = 0;