use metal::*;
use objc::rc::autoreleasepool;
const BINDLESS_TEXTURE_COUNT: NSUInteger = 100_000;
fn main() {
autoreleasepool(|| {
let device = Device::system_default().expect("no device found");
let tier = device.argument_buffers_support();
println!("Argument buffer support: {:?}", tier);
assert_eq!(MTLArgumentBuffersTier::Tier2, tier);
let texture_descriptor = TextureDescriptor::new();
texture_descriptor.set_width(1);
texture_descriptor.set_height(1);
texture_descriptor.set_depth(1);
texture_descriptor.set_texture_type(MTLTextureType::D2);
texture_descriptor.set_pixel_format(MTLPixelFormat::R8Uint);
texture_descriptor.set_storage_mode(MTLStorageMode::Private); println!("Texture descriptor: {:?}", texture_descriptor);
let size_and_align = device.heap_texture_size_and_align(&texture_descriptor);
let texture_size =
(size_and_align.size & (size_and_align.align - 1)) + size_and_align.align;
let heap_size = texture_size * BINDLESS_TEXTURE_COUNT;
let heap_descriptor = HeapDescriptor::new();
heap_descriptor.set_storage_mode(texture_descriptor.storage_mode()); heap_descriptor.set_size(heap_size);
println!("Heap descriptor: {:?}", heap_descriptor);
let heap = device.new_heap(&heap_descriptor);
println!("Heap: {:?}", heap);
let textures = (0..BINDLESS_TEXTURE_COUNT)
.map(|i| {
heap.new_texture(&texture_descriptor)
.unwrap_or_else(|| panic!("Failed to allocate texture {}", i))
})
.collect::<Vec<_>>();
let descriptor = ArgumentDescriptor::new();
descriptor.set_index(0);
descriptor.set_data_type(MTLDataType::Texture);
descriptor.set_texture_type(MTLTextureType::D2);
descriptor.set_access(MTLArgumentAccess::ReadOnly);
println!("Argument descriptor: {:?}", descriptor);
let encoder = device.new_argument_encoder(Array::from_slice(&[descriptor]));
println!("Encoder: {:?}", encoder);
let argument_buffer_size = encoder.encoded_length() * BINDLESS_TEXTURE_COUNT;
let argument_buffer = device.new_buffer(argument_buffer_size, MTLResourceOptions::empty());
textures.iter().enumerate().for_each(|(index, texture)| {
let offset = index as NSUInteger * encoder.encoded_length();
encoder.set_argument_buffer(&argument_buffer, offset);
encoder.set_texture(0, texture);
});
let queue = device.new_command_queue();
let command_buffer = queue.new_command_buffer();
let render_pass_descriptor = RenderPassDescriptor::new();
let encoder = command_buffer.new_render_command_encoder(render_pass_descriptor);
encoder.set_fragment_buffer(0, Some(&argument_buffer), 0);
encoder.use_heap_at(&heap, MTLRenderStages::Fragment);
encoder.end_encoding();
command_buffer.commit();
});
}