I am currently trying to use Tier 2 Argument Buffers with an array of buffers to access an indirect buffer but am running into some issues.
I am trying to get a basic example up and running but am having trouble getting the shader to read the value in the buffer.
Accessing the buffer directly, without an argument buffer, works fine and shows the expected value (12345).
The argument buffer shows the buffer as well (has the same cpu address in the debugger), but it seems to have a different device address than the direct one, and also returns 0xDEADBEEF instead of the correct value, which I assume is out of bounds memory or such.
The metal debugger, however, correctly links together the buffers, so I can inspect the buffer in the debugger through the argument buffer, and it contains the correct value.
I have the following (Rust) code:
This is the compute kernel (with Xcode debug annotations):
If anyone has any ideas as to why the buffer access seems to be invalid, I'd greatly appreciate it.
I am trying to get a basic example up and running but am having trouble getting the shader to read the value in the buffer.
Accessing the buffer directly, without an argument buffer, works fine and shows the expected value (12345).
The argument buffer shows the buffer as well (has the same cpu address in the debugger), but it seems to have a different device address than the direct one, and also returns 0xDEADBEEF instead of the correct value, which I assume is out of bounds memory or such.
The metal debugger, however, correctly links together the buffers, so I can inspect the buffer in the debugger through the argument buffer, and it contains the correct value.
I have the following (Rust) code:
Code Block rust // Setup let argument_desc = mtl::ArgumentDescriptor::new(); argument_desc.set_data_type(mtl::MTLDataType::Pointer); argument_desc.set_index(0); argument_desc.set_array_length(1024); let encoder = device.new_argument_encoder(mtl::Array::from_slice(&[argument_desc])); let argument_buffer = device.new_buffer(encoder.encoded_length(), mtl::MTLResourceOptions::empty()); encoder.set_argument_buffer(&argument_buffer, 0); let buffer = self.device.new_buffer_with_data( [12345u32].as_ptr() as _, mem::size_of::<u32>() as _, mtl::MTLResourceOptions::StorageModeShared | mtl::MTLResourceOptions::CPUCacheModeDefaultCache ); encoder.set_buffer(0, &buffer, 0); // Command Encoding let encoder = command_buffer.new_compute_command_encoder(); // ...set pipeline state encoder.set_buffer(0, Some(&bufferArray), 0); encoder.use_resource(&buffer, mtl::MTLResourceUsage::Read); encoder.set_bytes( 1, mem::size_of::<u32>() as _, &0 as *const _ as _, ); encoder.set_buffer( 2, Some(&buffer), 0, ); encoder.dispatch_thread_groups( mtl::MTLSize { width: 1, height: 1, depth: 1, }, mtl::MTLSize { width: 1, height: 1, depth: 1, }, );
This is the compute kernel (with Xcode debug annotations):
Code Block msl #include <metal_stdlib> #include <simd/simd.h> using namespace metal; struct Argument { constant uint32_t *ptr; }; kernel void main0( constant Argument *bufferArray [[buffer(0)]], // bufferArray = 0x400400000 constant uint32_t& buffer_index [[buffer(1)]], // buffer_index = 0 constant uint32_t *buffer [[buffer(2)]] // buffer = 0x400024000 ) { uint32_t x = *buffer; // x = 12345 constant uint32_t *ptr = bufferArray[buffer_index].ptr; // ptr = 0x40002000 uint32_t y = *ptr; // y = 0xDEADBEEF }
If anyone has any ideas as to why the buffer access seems to be invalid, I'd greatly appreciate it.