获取帧缓冲区并写入PNG(ObjectiveCPP/Metal)

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

目标:

// HIGH LEVEL
// create a texture
// render the current view to it
// write the texture to png at file path
// release texture / buffers?

我尝试解决方案(尚未编译):

void OutputFrameBuffer(const char *filepath) {
  mvGraphics &graphics = GContext->graphics;
  mvGraphics_Metal *graphicsData =
      (mvGraphics_Metal *)graphics.backendSpecifics;

  mvViewportData *_view =
      (mvViewportData *)GContext->viewport->platformSpecifics;
  id<CAMetalDrawable> drawable = _view->layer.nextDrawable;

  id<MTLCommandBuffer> commandBuffer =
      [graphicsData->commandQueue commandBuffer];

  // Encode a render pass to render the image to the drawable texture.
  [self drawScene:view withCommandBuffer:commandBuffer];

  id<MTLTexture> readTexture = drawable.texture;

  MTLOrigin readOrigin = MTLOriginMake(region.origin.x, region.origin.y, 0);
  MTLSize readSize = MTLSizeMake(region.size.width, region.size.height, 1);

  const id<MTLBuffer> pixelBuffer =
      [self readPixelsWithCommandBuffer:commandBuffer
                            fromTexture:readTexture
                               atOrigin:readOrigin
                               withSize:readSize];

  NSUInteger bytesPerPixel = sizeofPixelFormat(readTexture.pixelFormat);
  NSUInteger bytesPerRow = size.width * bytesPerPixel;
  NSUInteger bytesPerImage = size.height * bytesPerRow;

  id<MTLBuffer> _readBuffer =
      [readTexture.device newBufferWithLength:bytesPerImage
                                      options:MTLResourceStorageModeShared];

  id<MTLBlitCommandEncoder> blitEncoder = [commandBuffer blitCommandEncoder];

  [blitEncoder copyFromTexture:readTexture
                   sourceSlice:0
                   sourceLevel:0
                  sourceOrigin:origin
                    sourceSize:size
                      toBuffer:_readBuffer
             destinationOffset:0
        destinationBytesPerRow:bytesPerRow
      destinationBytesPerImage:bytesPerImage];

  [blitEncoder endEncoding];
  [commandBuffer commit];

  // The app must wait for the GPU to complete the blit pass before it can
  // read data from _readBuffer.
  [commandBuffer waitUntilCompleted];

  // Read texture data from the GPU
  NSUInteger _bytesPerRow = readTexture.width * 4; // Assuming RGBA8 format
  NSUInteger bufferSize = bytesPerRow * readTexture.height;
  //   void *buffer = malloc(bufferSize);
  //   [renderTexture getBytes:buffer
  //               bytesPerRow:bytesPerRow
  //                fromRegion:MTLRegionMake2D(0, 0, renderTexture.width,
  //                                           renderTexture.height)
  //               mipmapLevel:0];

  // Convert char* fname to NSString
  std::string fnameString(filepath);
  NSString *filePath = [NSString stringWithUTF8String:fnameString.c_str()];

  // Save texture data to a file
  NSData *imageData = [NSData dataWithBytesNoCopy:_readBuffer
                                           length:bufferSize
                                     freeWhenDone:YES];
  [imageData writeToFile:filePath atomically:YES];

  // Cleanup
  free(_readBuffer);
}

C 文件中暴露的数据:$GContext: mvContext$ 其中包含 2 个结构体:

mvViewportData
{
    GLFWwindow*   handle = nullptr;
    CAMetalLayer* layer = nullptr;
};

struct mvGraphics_Metal
{
    MTLRenderPassDescriptor* renderPassDescriptor;
    id <MTLCommandQueue>     commandQueue;
    id <MTLDevice>           device;
};

我正在尝试为开源 Dearpygui 做出贡献,因为我希望它能够在我的 Mac 上运行!

我尝试改编以下示例 https://developer.apple.com/documentation/metal/textures/creating_and_sampling_textures https://developer.apple.com/documentation/metal/onscreen_presentation/reading_pixel_data_from_a_drawable_texture

但我觉得我错过了一些东西,即我从 ChatGPT 获得了 png 的纹理,但我不相信它。还有上下文区域和图像大小。我已经超出了我的深度。我还没有编译:D

metal objective-c++ dearpygui
1个回答
0
投票

与其尝试让 ChatGPT 为您编写一个函数,我建议您查看 Stack Overflow 上的工作示例,例如这个已回答的问题,该问题从可绘制对象

CGImage
创建
UIImage
MTLTexture
:

在 swift 中使用 Metal 拍摄当前屏幕的快照

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