Issue accessing Buffer through Argument Buffer

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:
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.


Post not yet marked as solved Up vote post of svenknobloch Down vote post of svenknobloch
1.6k views

Replies

Have you figure out the solution to this? Sorry for necroposting, but I haven't found the issue anywhere else.