libMTLHud.dylib`Renderer::DrawText:

问题描述 投票:0回答:1

我编写了一个由metal渲染的视图,当视图初始化时,我为该视图创建了一个MTLCommandQueue。但是如果我同时在屏幕上放置两个视图,程序就会崩溃。谁能告诉我为什么?

* thread #9, queue = 'com.Metal.CompletionQueueDispatch', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
  * frame #0: 0x00000002299221f0 libMTLHud.dylib`Renderer::DrawText(char const*, int, unsigned int) + 340
    frame #1: 0x0000000229924d68 libMTLHud.dylib`Overlay::onPresent(id<CAMetalDrawable>) + 2136
    frame #2: 0x0000000229923ab0 libMTLHud.dylib`CAMetalDrawable_present(void (*)(), objc_object*, objc_selector*) + 68
    frame #3: 0x0000000229923dc0 libMTLHud.dylib`invocation function for block in void replaceMethod<void>(objc_class*, objc_selector*, void (*)(void (*)(), objc_object*, objc_selector*)) + 56
    frame #4: 0x00000001a95f5c04 Metal`__45-[_MTLCommandBuffer presentDrawable:options:]_block_invoke + 104
    frame #5: 0x00000001a950ff48 Metal`MTLDispatchListApply + 52
    frame #6: 0x00000001a9505b84 Metal`-[_MTLCommandBuffer didScheduleWithStartTime:endTime:error:] + 300
    frame #7: 0x0000000215d21ed0 IOGPU`IOGPUNotificationQueueDispatchAvailableCompletionNotifications + 128
    frame #8: 0x0000000215d15880 IOGPU`__IOGPUNotificationQueueSetDispatchQueue_block_invoke + 64
    frame #9: 0x0000000102fd611c libdispatch.dylib`_dispatch_client_callout4 + 20
    frame #10: 0x0000000102ff43ac libdispatch.dylib`_dispatch_mach_msg_invoke + 516
    frame #11: 0x0000000102fddea8 libdispatch.dylib`_dispatch_lane_serial_drain + 376
    frame #12: 0x0000000102ff5370 libdispatch.dylib`_dispatch_mach_invoke + 492
    frame #13: 0x0000000102fddea8 libdispatch.dylib`_dispatch_lane_serial_drain + 376
    frame #14: 0x0000000102fdee68 libdispatch.dylib`_dispatch_lane_invoke + 472
    frame #15: 0x0000000102fddea8 libdispatch.dylib`_dispatch_lane_serial_drain + 376
    frame #16: 0x0000000102fdee34 libdispatch.dylib`_dispatch_lane_invoke + 420
    frame #17: 0x0000000102febcbc libdispatch.dylib`_dispatch_workloop_worker_thread + 740
    frame #18: 0x00000001fb7e3df8 libsystem_pthread.dylib`_pthread_wqthread + 288

我尝试在渲染时添加锁,但不起作用。

ios metal
1个回答
0
投票

您可以为两个视图使用一个共享队列,但每个视图都必须使用其渲染句柄和命令缓冲区的副本。在这里,我为您准备了一个小片段(标头和实现)作为示例,您可以将其用作起始源。

MetalView.h

#import <Metal/Metal.h>
#import <MetalKit/MTKView.h>


#define SHARED_CLASS(classname) \
+ (id) Shared##classname { \
    static dispatch_once_t pred = 0; \
    static id _sharedObject = nil; \
    dispatch_once(&pred, ^{ \
        _sharedObject = [[self alloc] init]; \
    }); \
    return _sharedObject; \
}

NS_ASSUME_NONNULL_BEGIN

@interface MetalQueue : NSObject

@property (atomic, readonly) id<MTLDevice> device;
@property (atomic, readonly) id<MTLCommandQueue> queue;

+ (instancetype)SharedMetalQueue;

@end

NS_ASSUME_NONNULL_END

NS_ASSUME_NONNULL_BEGIN

@interface MetalView : MTKView<MTKViewDelegate>

@end

NS_ASSUME_NONNULL_END

MetalQueue 具有在多个视图之间共享的共享单例属性。

MetalView.m

#import "MetalView.h"

@implementation MetalQueue

- (instancetype)init {
  if (self) {
    _device = MTLCreateSystemDefaultDevice();
    assert(_device);
    _queue = [_device newCommandQueue];
  }
  return self;
}

SHARED_CLASS(MetalQueue);

@end

@implementation MetalView

- (instancetype)initWithCoder:(NSCoder *)coder {
  if (self) {
    self.delegate = self;
    self.framebufferOnly = true;
    self.enableSetNeedsDisplay = true;
    [self setPaused: true];
    
  }
  return [super initWithCoder: coder];
  
}

- (void)drawInMTKView:(nonnull MTKView *)view {
  view.device = [MetalQueue SharedMetalQueue].device;
  id<MTLCommandBuffer> commandBuffer = [[MetalQueue SharedMetalQueue].queue commandBuffer];
  id<MTLCommandEncoder> commandEncoder = [commandBuffer renderCommandEncoderWithDescriptor: view.currentRenderPassDescriptor];
  
  if (view.currentDrawable) {
    [commandEncoder endEncoding];
    
    if ([view tag] == 0) {
      view.clearColor = MTLClearColorMake(1.0, 0.0, 0.0, 1.0);

    }
    else {
      view.clearColor = MTLClearColorMake(0.0, 1.0, 0.0, 1.0);
    }
    
    [commandBuffer presentDrawable:view.currentDrawable];
    
    [commandBuffer commit];
  }
  
}

- (void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size {
  
}


@end

MetalView 使用自渲染委托实现。

© www.soinside.com 2019 - 2024. All rights reserved.