NOTE: For buffers (device, constant and threadgroup), textures or samplers the
index
value that is used to specify the buffer, texture or sampler index must be unique.
Multiple buffer, texture or sampler arguments with the same
index
value generate a
compilation error unless they are declared with a function constant attribute (see
section 4.10.1).
4.3.1.1
Vertex Function Example with Resources and Outputs to Device Memory
The following example is a vertex function,
render_vertex
, which outputs to device memory in
the array
xform_output
, which is a function argument specified with the
device
attribute
(introduced in section 4.2.1). All the
render_vertex
function arguments are specified with the
buffer(0)
,
buffer(1)
,
buffer(2)
, and
buffer(3)
attributes (introduced in section 4.3.1).
The
position
attribute shown in this example is discussed in section 4.3.3.
struct VertexOutput {
float4 position [[position]];
float4 color;
float2 texcoord;
};
struct VertexInput {
float4
position;
float3 normal;
float2 texcoord;
};
constexpr constant uint MAX_LIGHTS = 4;
struct LightDesc {
uint num_lights;
float4 light_position[MAX_LIGHTS];
float4 light_color[MAX_LIGHTS];
float4 light_attenuation_factors[MAX_LIGHTS];
};
vertex void
render_vertex(const device VertexInput* v_in [[
buffer(0)]],
constant float4x4& mvp_matrix [[
buffer(1)]],
constant LightDesc& light_desc [[
buffer(2)]],
2017-9-12 | Copyright © 2017 Apple Inc. All Rights Reserved.
Page of
61
174
device VertexOutput* xform_output [[
buffer(3)]],
uint v_id [[
vertex_id]] )
{
VertexOutput v_out;
v_out.position = v_in[v_id].position * mvp_matrix;
v_out.color = do_lighting(v_in[v_id].position, v_in[v_id].normal,
light_desc);
v_out.texcoord = v_in[v_id].texcoord;
//
output position to a buffer
xform_output[v_id] = v_out;
}
4.3.1.2
Raster Order Groups
Loads and stores to buffers (in
device
memory) and textures in a fragment function are
unordered. The
[[raster_order_group(index)]]
attribute used for a buffer or texture
guarantees the order of accesses for any overlapping fragments from different primitives that
map to the same
(x,y)
pixel coordinate and sample, if per-sample shading is active.
The
[[raster_order_group(index)]]
attribute can be specified on a texture (which is
always in
device
memory) or a buffer that is declared in
device
memory, but not in either the
threadgroup
or
constant
address space. The
[[raster_order_group(index)]]
attribute
cannot be used with a struct or class.
Fragment function invocations that mark overlapping accesses to a buffer or texture with the
[[raster_order_group(index)]]
attribute are executed in the same order as the geometry
is submitted. So for overlapping fragment function invocations, writes performed by a fragment
function invocation to a buffer or texture marked with the
[[raster_order_group(index)]]
attribute must be available to be read by a subsequent invocation and must not affect reads by
a previous invocation. Similarly, reads performed by a fragment function invocation must reflect
writes by a previous invocation and must not reflect writes by a subsequent invocation.
The
index
in
[[raster_order_group(index)]]
is an integer value that specifies a rasterizer
order ID, which provides finer grained control over the ordering of loads and stores. For
example, if two buffers A and B are marked with different rasterizer order ID values, then loads
and stores to buffers A and B for overlapping fragments can be synchronized independently.
Example:
fragment void
my_fragment(texture2d
texA
[[raster_order_group(0), texture(0)]],
…)
2017-9-12 | Copyright © 2017 Apple Inc. All Rights Reserved.
Page of
62
174
{
ushort2 coord;
float4 clr = texA.load(coord);
//
do operations on clr
clr = …;
texA.write(clr, coord);
}
For an argument buffer, the
[[raster_order_group(index)]]
attribute can be used on a
buffer or texture member in a struct.
4.3.2
Struct of Buffers and Textures
Arguments to a graphics, kernel or user function can be a struct or a nested struct whose
members are buffers, textures or samplers only. Such a struct must be passed by value. Each
member of such a struct passed as the argument type to a graphics or kernel function can have
an attribute to specify its location (as described in section 4.3.1).
Example of a struct passed as an argument:
struct Foo {
texture2d
a [[texture(0)]];
depth2d b [[texture(1)]];
};
kernel void
my_kernel(Foo f)
{…}
Below are some examples of invalid use cases that should result in a compilation error.
kernel void
my_kernel(device Foo& f) // illegal use
{…}
struct MyResources {
texture2d a [[texture(0)]];
depth2d b [[texture(1)]];
int c;
};
2017-9-12 | Copyright © 2017 Apple Inc. All Rights Reserved.
Page of
63
174