Loading [MathJax]/jax/output/CommonHTML/config.js
社区首页 >问答首页 >从泛型MTLBuffer中读取内容?

从泛型MTLBuffer中读取内容?
EN

Stack Overflow用户
提问于 2020-08-26 22:46:57
回答 1查看 397关注 0票数 1

在我的应用程序中,我有一个使用泛型类型实例化的MTLBuffer。在一种特定情况下,缓冲区将保存与点云中的粒子相关的值,并如此定义;

代码语言:javascript
代码运行次数:0
复制
struct ParticleUniforms {
    simd_float3 position;
    simd_float3 color;
    float confidence;
};

我像这样实例化我的MTLBuffer

代码语言:javascript
代码运行次数:0
复制
guard let buffer = device.makeBuffer(length: MemoryLayout<Element>.stride * count, options: options) else {
   fatalError("Failed to create MTLBuffer.")
}

然而,我正在努力理解如何读取缓冲区的内容。更重要的是,我希望将缓冲区中每个项目的一个元素复制到CPU上的一个数组中,稍后我将使用该数组。

实际上,buffer保存了一个ParticleUniforms集合,我希望访问每个项目的position值,将该位置保存到一个单独的数组中。

我在Stack Overflow上看到的所有示例似乎都显示MTLBuffer持有一个浮点数的集合,尽管我还没有看到任何使用泛型类型的示例。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-08-28 13:40:22

似乎你想要实现的目标只能用C结构来实现,C结构将每个成员放在一个连续的块中(C结构的数组必须是连续的,但MemoryLayout<Type>.stride将考虑任何潜在的填充)。Swift结构属性may not be contiguous,所以下面访问成员值的方法不能以实际的方式工作。不幸的是,在使用void*时,您需要知道数据描述了什么,这并不是特别适合Swift泛型类型。但是,我将提供一个潜在的解决方案。

C文件:

代码语言:javascript
代码运行次数:0
复制
#ifndef Test_h
#define Test_h

#include <simd/simd.h>

typedef struct {
    vector_float3 testA;
    vector_float3 testB;
} CustomC;

#endif /* Test_h */

Swift文件(假定为桥接头)

代码语言:javascript
代码运行次数:0
复制
import Metal

// MARK: Convenience
typealias MTLCStructMemberFormat = MTLVertexFormat

@_functionBuilder
struct ArrayLayout { static func buildBlock<T>(_ arr: T...) -> [T] { arr } }

extension MTLCStructMemberFormat {
    var stride: Int {
        switch self {
        case .float2:  return MemoryLayout<simd_float2>.stride
        case .float3:  return MemoryLayout<simd_float3>.stride
        default:       fatalError("Case unaccounted for")
        }
    }
}

// MARK: Custom Protocol
protocol CMetalStruct {
    /// Returns the type of the `ith` member
    static var memoryLayouts: [MTLCStructMemberFormat] { get }
}

// Custom Allocator
class CustomBufferAllocator<Element> where Element: CMetalStruct {
    
    var buffer: MTLBuffer!
    var count: Int
    
    init(bytes: UnsafeMutableRawPointer, count: Int, options: MTLResourceOptions = []) {
        guard let buffer = device.makeBuffer(bytes: bytes, length: count * MemoryLayout<Element>.stride, options: options) else {
            fatalError("Failed to create MTLBuffer.")
        }
        self.buffer = buffer
        self.count = count
    }
    
    func readBufferContents<T>(element_position_in_array n: Int, memberID: Int, expectedType type: T.Type = T.self)
        -> T {
        let pointerAddition = n * MemoryLayout<Element>.stride
            let valueToIncrement = Element.memoryLayouts[0..<memberID].reduce(0) { $0 + $1.stride }
        return buffer.contents().advanced(by: pointerAddition + valueToIncrement).bindMemory(to: T.self, capacity: 1).pointee
    }
    
    func extractMembers<T>(memberID: Int, expectedType type: T.Type = T.self) -> [T] {
        var array: [T] = []
 
        for n in 0..<count {
            let pointerAddition = n * MemoryLayout<Element>.stride
            let valueToIncrement = Element.memoryLayouts[0..<memberID].reduce(0) { $0 + $1.stride }
            let contents = buffer.contents().advanced(by: pointerAddition + valueToIncrement).bindMemory(to: T.self, capacity: 1).pointee
            array.append(contents)
        }
        
        return array
    }
}

// Example

// First extend the custom struct to conform to out type
extension CustomC: CMetalStruct {
    @ArrayLayout static var memoryLayouts: [MTLCStructMemberFormat] {
        MTLCStructMemberFormat.float3
        MTLCStructMemberFormat.float3
    }
}

let device = MTLCreateSystemDefaultDevice()!
var CTypes = [CustomC(testA: .init(59, 99, 0), testB: .init(102, 111, 52)), CustomC(testA: .init(10, 11, 5), testB: .one), CustomC(testA: .zero, testB: .init(5, 5, 5))]

let allocator = CustomBufferAllocator<CustomC>(bytes: &CTypes, count: 3)
let value = allocator.readBufferContents(element_position_in_array: 1, memberID: 0, expectedType: simd_float3.self)
print(value)

// Prints SIMD3<Float>(10.0, 11.0, 5.0)

let group = allocator.extractMembers(memberID: 1, expectedType: simd_float3.self)
print(group)

// Prints [SIMD3<Float>(102.0, 111.0, 52.0), SIMD3<Float>(1.0, 1.0, 1.0), SIMD3<Float>(5.0, 5.0, 5.0)]

这类似于MTLVertexDescriptor,不同之处在于内存是手动访问的,而不是通过传递给片段顶点着色器的每个实例的[[stage_in]]属性和参数表访问的。您甚至可以扩展分配器以接受带有属性名称的字符串参数,并保存一些映射到成员ID的字典。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63606753

复制
相关文章
Dart中的泛型方法、泛型类、泛型接口
为了能在一个方法里实现传入什么数据类型就返回什么数据类型,可以利用泛型将方法写成下面这样:
越陌度阡
2020/12/10
3.8K0
Dart中的泛型方法、泛型类、泛型接口
TypeScript中泛型及泛型函数、泛型类、泛型接口,泛型约束,一文读懂
 最近在学TypeScript,然后整理了一下关于TypeScript中泛型的一些笔记。
痴心阿文
2022/11/21
2.8K0
C#泛型入门泛型类、泛型集合、泛型方法、泛型约束、泛型委托
给.neter们整理了一份《.NET/C#面试手册》,目前大约4万字左右,初衷也很简单,就是希望在面试的时候能够帮助到大家,减轻大家的负担和节省时间。对于没有跳槽打算的也可以复习一下相关知识点,就当是查缺补漏!
全栈程序员站长
2022/09/14
2.6K0
C#泛型入门泛型类、泛型集合、泛型方法、泛型约束、泛型委托
【Java 泛型】泛型用法 ( 泛型类用法 | 泛型方法用法 | 泛型通配符 ? | 泛型安全检查 )
泛型类用法 : 使用时先声明泛型 , 如果不声明泛型 , 则表示该类的泛型是 Object 类型 ;
韩曙亮
2023/03/29
10.2K0
【Java 泛型】泛型用法 ( 泛型类用法 | 泛型方法用法 | 泛型通配符 ? | 泛型安全检查 )
【Java 泛型】泛型简介 ( 泛型类 | 泛型方法 | 静态方法的泛型 | 泛型类与泛型方法完整示例 )
泛型 可以 简单理解为 参数化类型 , 主要作用在 类 , 方法 , 接口 上 ;
韩曙亮
2023/03/29
15.4K0
【Java 泛型】泛型简介 ( 泛型类 | 泛型方法 | 静态方法的泛型 | 泛型类与泛型方法完整示例 )
Java进阶:【泛型】认识泛型,泛型方法,泛型类,泛型接口和通配符
例如关于这个元素如何保存,如何管理等是确定的,因此此时把元素的类型设计成一个参数,这个类型参数叫做泛型。
冷环渊
2021/11/29
3.5K0
Java进阶:【泛型】认识泛型,泛型方法,泛型类,泛型接口和通配符
深入理解Java泛型(三)-泛型擦除及其相关内容
我们看输出发现,class1和class2居然是同一个类型ArrayList,在运行时我们传入的类型变量String和Integer都被丢掉了。Java语言泛型在设计的时候为了兼容原来的旧代码,Java的泛型机制使用了“擦除”机制。我们来看一个更彻底的例子:
Anymarvel
2020/08/06
6070
泛型(泛型擦除)【java基础—-泛型】
Java泛型是J2 SE1.5中引入的一个新特性,其本质是参数化类型,也就是说所操作的数据类型被指定为一个参数(type parameter),这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
全栈程序员站长
2022/11/02
2.6K0
泛型(泛型擦除)【java基础—-泛型】
【Kotlin】泛型 ① ( 泛型类 | 泛型参数 | 泛型函数 | 多泛型参数 | 泛型类型约束 )
将 泛型参数 T 放在 尖括号 <T> 中 , 该泛型参数放在 类名后 , 主构造函数之前 , 该泛型参数 T 是 类型占位符 ,
韩曙亮
2023/03/30
2.9K0
泛型接口,泛型类和泛型通配符
泛型的使用位置,除了最常见的约束集合元素,还可以使用在接口,类,方法上面。最本质的原因就是为了在使用接口,类,方法的时候,可以将类型作为参数,进行类型的参数传递。这样可以使程序的编写更加的灵活,在创建对象,调用方法的时候动态的指定类型,所以泛型也可以理解为类型的参数化。
用户5745563
2019/07/04
2.3K0
泛型接口,泛型类和泛型通配符
Java 泛型擦除_泛型和泛型擦除
如果仅凭直觉来看,该程序可能会输出 false 这个结果,但在具体的环境下运行时会输出 true 。这很令人费解,这是为什么呢?
全栈程序员站长
2022/11/01
2.4K0
JAVA中的泛型
程序在运行时发生了问题java.lang.ClassCastException。 为什么会发生类型转换异常呢? 我们来分析下:由于集合中什么类型的元素都可以存储。导致取出时强转引发运行时 ClassCastException。 怎么来解决这个问题呢?
星哥玩云
2022/09/14
1.4K0
JAVA中的泛型
Java泛型中<?> 和 <? extends Object>的异同分析
点击上方蓝色“程序猿DD”,选择“设为星标” 回复“资源”获取独家整理的学习资料! 作者 | 刘一手 来源 | 公众号「锅外的大佬」 Java Generics – <?> vs <? extend
程序猿DD
2023/04/17
7860
Java泛型中<?> 和 <? extends Object>的异同分析
泛型泛型知多少
泛型是JDK 5引入的概念,泛型的引入主要是为了保证java中类型的安全性,有点像C++中的模板。
程序那些事
2020/07/08
1.1K0
Rust中的泛型
泛型程序设计是程序设计语言的一种风格或范式。泛型允许程序员在强类型程序设计语言中编写代码时使用一些以后才指定的类型,在实例化时作为参数指明这些类型。泛型编程的中心思想是从携带类型信息的具体的算法中抽象出来,得到一种可以与不同的数据类型表示相结合的算法,从而生成各种有用的软件。泛型编程是一种软件工程中的解耦方法,很多时候,我们的算法并不依赖某种特定的具体类型,通过这种方法,我们就可以将“类型”从算法和数据结构的具体示例中抽象出来。
端碗吹水
2022/06/01
9400
java中的泛型
java语言的多态性让我们可以把某些只能在运行时确定的类型在编译时使用父类或者父接口表示,这确实解决了很多问题。但有时程序员在声明某些变量时不知道它的具体父类或父接口,只能选择公共父类Object类型,这很不方便。
别团等shy哥发育
2023/02/25
2.7K0
java中的泛型
Java中的泛型
Java 为什么要发明泛型?泛型给我们开发带来了哪些便利,对于代码层面来说,泛型又给我们带来了什么?
袁新栋-jeff.yuan
2020/08/26
1.1K0
Java中的泛型
【Flutter】Dart 泛型 ( 泛型类 | 泛型方法 | 特定类型约束的泛型 )
泛型作用 : 为 类 , 接口 , 方法 提供复用性 , 支持类型不确定的数据类型 ;
韩曙亮
2023/03/28
5.4K0
什么是泛型以及在集合中泛型的使用[通俗易懂]
泛型最常与集合使用,因为泛型最开始开始被加入Java就是为了解决集合向下转型一类问题的。如果我们有这样一个需求:定义一个描述类圆,要求圆中的数据类型是不确定的,也就是声名属性的时候,属性类型是不确定的。比如描述类圆中有半径,要求半径可以用int,也可以用double。那么此时数据类型不确定,就使用泛型,把数据类型参数化。
全栈程序员站长
2022/06/25
2.1K0
TS 从 0 到 1 - 泛型
在 C# 和 Java 中,可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。这样用户就可以以自己的数据类型来使用组件。
Cellinlab
2023/05/17
4060

相似问题

从泛型对象列表中读取泛型值

11

用Swift从MTLBuffer读取数据

210

金属中MTLBuffer的更新内容

11

从用户输入读取泛型类型

30

从DataReader读取数据的泛型方法

20
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文