lok*_*oki 1 objective-c ios metal metalkit
在Metal shader中,声明类似const constant Vertex *vertexArray [[buffer(0)]](const constant我的意思是)的变量的目的是什么?为什么仅靠常数还不够?而且,constant和之间有什么区别const?
同样,const device和之间的区别是constant什么?
const是类型限定符。constant和device是地址空间。
const 阻止您修改其适用的事物:
int a = 15;
a = 16; // Fine; reassigning to a non-const variable
const int b = 15;
b = a; // Error: attempt to write to a read-only constant
int d = 18;
int const* c = &a;
*c = 17; // Error: attempt to write value through a pointer to const int
c = &d; // Fine; reassigning (a different address) to a (non-const) pointer
int *const e = &d;
*e = a; // Fine; assigning to pointee through pointer to non-const int
e = c; // Error: attempt to reassign const pointer
Run Code Online (Sandbox Code Playgroud)
希望这些例子能充分说明变量和常量的语义,以及在指针情况下规则如何工作。
在Metal中,指针始终驻留在特定的地址空间中。如果您在Metal着色器函数中使用自动存储的变量的地址(即“局部”变量),则该指针位于线程地址空间中。另一方面,缓冲区参数始终位于常量或设备地址空间中。
device缓冲区用于保存内存,该内存的元素将被大致访问一次,就像在顶点函数中按顺序获取顶点数据时那样。另一方面,constant与统一数据一样,缓冲区保存的数据可能会被函数的许多调用访问。
您不能在constant地址空间中写入缓冲区。这是此答案中最重要的一句话:地址空间中的所有指针constant都是隐式const限定的。
您可以在恒定的地址空间中形成新的指针,并且通过上述规则,可以重新分配它们。但是尝试写给他们的对象将产生编译器错误。
假设您使用以下参数编写一个片段函数:
constant Light *lights [[buffer(0)]]
Run Code Online (Sandbox Code Playgroud)
然后在函数体中可以这样说:
constant Light *light = &lights[0];
Run Code Online (Sandbox Code Playgroud)
和这个:
light = &lights[1];
Run Code Online (Sandbox Code Playgroud)
但这不是:
light->color = float4(1, 1, 1, 1); // Error: attempt to write to variable with const-qualified type "const constant Light *"
Run Code Online (Sandbox Code Playgroud)
再次注意,在最后一个示例中,即使我们没有说常量指针应该是指向const的指针,也是如此。因此,constant用const(在星号之前)进一步限定指针是多余的。
现在让我们谈谈device指针。
与constant始终为只读的缓冲区相反,在许多情况下都可以写入device缓冲区。但是,您通常将设备缓冲区视为只读(例如,在大多数顶点函数中)。为了向编译器指示此意图,可以将其添加const到设备缓冲区指针参数。这将防止您无意中写入只打算读取的缓冲区。如果device在不适当的上下文中使用指向非常量类型的指针,则Metal着色器编译器的最新版本会发出警告,这就是为什么养成编写const device此类参数的习惯通常是一个好主意的原因。
但是写作const constant是多余的,而且从来没有必要。
| 归档时间: |
|
| 查看次数: |
55 次 |
| 最近记录: |