Как получить доступ к членам ссылки C ++ или указателя в ядре Metal? - PullRequest
4 голосов
/ 26 апреля 2020

Я всегда получаю ту же ошибку при попытке использовать ссылки из любого адресного пространства (константы, устройства или потока). Это не компилируется и выдает странную ошибку:

struct Foo {
    int getter() const {
        return 1;
    }
};

void use_foo(constant Foo& foo) {
    int x = foo.getter(); // error here
}

kernel void test_kernel(constant Foo& foo [[buffer(0)]]) {
    use_foo(foo);
}

Ошибка:

не может инициализировать параметр объекта типа 'const Foo' с выражением типа 'const константа Foo '

Заменить constant на любой другой спецификатор адреса памяти, и это та же общая ошибка. Не имеет значения, была ли это ссылка, переданная непосредственно в ядро, или локальная ссылка потока, созданная функцией - я не могу использовать эти ссылки в любом случае из-за этой ошибки. Являются ли они постоянными или неконстантными ссылками, также не имеет значения.

Единственный обходной путь - просто взять копию Foo вместо попытки использовать ссылку на нее. Я никогда не понимал эту странную ошибку. Я также попытался принять аргумент за constant const Foo& и другие попытки и ошибки.

Может кто-нибудь посоветовать, как на самом деле использовать ссылку?

Я получаю похожую ошибку, если я переключаюсь на использование указатель вместо ссылки:

enter image description here

из этого:

struct Foo {
    int getter() const {
        return 1;
    }
};

void use_foo(constant const Foo* const foo) {
    int x = foo->getter(); // error here
}

kernel void test_kernel(constant Foo* foo [[buffer(0)]]) {
    use_foo(foo);
}

Аналогичные попытки экспериментировать вокруг использования const или не в разных местах без разницы.

1 Ответ

3 голосов
/ 27 апреля 2020

Ваша квалификация функции-члена обычно должна соответствовать типу объекта вызываемого. Если вы хотите вызвать такой метод для объекта const constant, вы можете квалифицировать свой метод следующим образом:

    int getter() const constant {
        return 1;
    }

В спецификации Metal Shading Language сказано (§4): "Любая переменная, являющаяся указателем или ссылкой, должна быть объявлена ​​с помощью [устройство, константа, поток, группа потоков или threadgroup_imageblock]" . Важно понимать, что аргумент this для функции-члена является указателем - в основном аргументом невидимой функции - и квалификация функции влияет на тип этого указателя. Фактически вы объявляете int getter(const constant Foo* this).

...