Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2021 Graphics & Games

WWDC21 · 21 min · Graphics & Games

Explore bindless rendering in Metal

Unleash the full potential of your shaders and implement modern rendering techniques by adding Argument Buffers to adopt bindless rendering. Learn how to make your entire scene and resources available to the GPU to make the most out of raytracing and rasterization pipelines.

Watch at developer.apple.com ↗

Transcript all transcripts

Code shown on screen · 12 snippets

Simple Intersection Kernel 2 objectivec · at 0:07 ↗
if(i.type == intersection_type::triangle)
{
  constant Instance& inst     = get_instance(i);
  constant Mesh&     mesh     = get_mesh(inst, i);
  constant Material& material = get_material(inst, i);
  
  color = shade_pixel(mesh, material, i);
}   

outImage.write(color, tid);
PBR fragment shading requires several textures objectivec · at 0:08 ↗
fragment half4 pbrFragment(ColorInOut in [[stage_in]],
                           texture2d< float > albedo    [[texture(0)]],
                           texture2d< float > roughness [[texture(1)]],
                           texture2d< float > metallic  [[texture(2)]],
                           texture2d< float > occlusion [[texture(3)]])
{	
	half4 color = calculateShading(in, albedo, roughness, metallic, occlusion);
	return color;
}
Bindless makes all textures available via AB navigation objectivec · at 0:09 ↗
fragment half4 pbrFragmentBindless(ColorInOut in [[stage_in]], 
                                   device const Scene* pScene [[buffer(0)]])
{
	device const Instance& instance = pScene->instances[in.instance_id];
	device const Material& material = pScene->materials[instance.material_id];
	
	half4 color = calculateShading(in, material);
	
	return color;
}
Simple Intersection Kernel 1 objectivec · at 1:48 ↗
if (intersection.type == intersection_type::triangle) 
{
  // solid blue triangle
  color = float4(0.0f, 0.0f, 1.0f, 1.0f);
}   

outImage.write(color, tid);
Encoder creation objectivec · at 11:33 ↗
struct Instance
{
    constant Mesh*     pMesh            [[id(0)]];
    constant Material* pMaterial        [[id(1)]];
    constant float4x4  modelTransform   [[id(2)]];
};
Encoder via reflection objectivec · at 11:50 ↗
// Shader code references scene
kernel void RTReflections( constant Scene* pScene [[buffer(0)]] );
Argument Buffers referenced indirectly objectivec · at 13:08 ↗
MTLArgumentDescriptor* meshArg 
= [MTLArgumentDescriptor argumentDescriptor];

meshArg.index    = 0;
meshArg.dataType = MTLDataTypePointer;
meshArg.access   = MTLArgumentAccessReadOnly;

// Declare all other arguments (material and transform)
   
id<MTLArgumentEncoder> instanceEncoder 
= [device newArgumentEncoderWithArguments:@[meshArg, 
                                            materialArg, 
                                            transformArg]];
Navigation 1 objectivec · at 16:10 ↗
// Instance and Mesh

constant Instance& instance = pScene->instances[intersection.instance_id];
constant Mesh&     mesh     = instance.mesh[intersection.geometry_id];

// Primitive indices

ushort3 indices; // assuming 16-bit indices, use uint3 for 32-bit

indices.x = mesh.indices[ intersection.primitive_id * 3 + 0 ];
indices.y = mesh.indices[ intersection.primitive_id * 3 + 1 ];
indices.z = mesh.indices[ intersection.primitive_id * 3 + 2 ];
Navigation 2 objectivec · at 16:43 ↗
// Vertex data

packed_float3 n0 = mesh.normals[ indices.x ];
packed_float3 n1 = mesh.normals[ indices.y ];
packed_float3 n2 = mesh.normals[ indices.z ];

// Interpolate attributes

float3 barycentrics = calculateBarycentrics(intersection);
float3 normal       = weightedSum(n0, n1, n2, barycentrics);
Simple Intersection Kernel objectivec · at 17:15 ↗
if(i.type == intersection_type::triangle)
{
  constant Instance& inst     = get_instance(i);
  constant Mesh&     mesh     = get_mesh(inst, i);
  constant Material& material = get_material(inst, i);
  
  color = shade_pixel(mesh, material, i);
}   

outImage.write(color, tid);
PBR fragment shading requires several textures objectivec · at 19:30 ↗
fragment half4 pbrFragment(ColorInOut in [[stage_in]],
                           texture2d< float > albedo    [[texture(0)]],
                           texture2d< float > roughness [[texture(1)]],
                           texture2d< float > metallic  [[texture(2)]],
                           texture2d< float > occlusion [[texture(3)]])
{	
	half4 color = calculateShading(in, albedo, roughness, metallic, occlusion);
	
  return color;
}
Bindless makes all textures available via AB navigation objectivec · at 19:48 ↗
fragment half4 pbrFragmentBindless(ColorInOut in [[stage_in]], 
                                   device const Scene* pScene [[buffer(0)]])
{
	device const Instance& instance = pScene->instances[in.instance_id];
	device const Material& material = pScene->materials[instance.material_id];
	
	half4 color = calculateShading(in, material);
	
	return color;
}

Resources