реализация пользовательской ISlangFileSystem

Вопрос или проблема

В новейшей версии Vulkan SDK добавлена поддержка языка шейдеров Slang. Я пытаюсь использовать этот компилятор программно из кода C++ с реализации файловой системы (чтобы отслеживать подключения и перекомпилировать шейдеры во время выполнения).

    struct FileSystem : ISlangFileSystem {
        virtual SlangResult loadFile(char const* path, ISlangBlob** outBlob) override {
        }
    };

    struct SlangCompiler {
        slang::IGlobalSession* session = nullptr;
        slang::ICompileRequest* request = nullptr;
        FileSystem file_system;

        SlangCompiler() {
            SlangResult result;
            result = slang::createGlobalSession(&session);
            result = session->createCompileRequest(&request);           
            request->setFileSystem(&file_system);
        }

        ~SlangCompiler() {
            request->release();
            session->release();
            request = nullptr;
            session = nullptr;
        }
    };

Я получаю следующие ошибки (сокращено для краткости)

error C2259: '`anonymous-namespace'::FileSystem': cannot instantiate abstract class
SlangResult ISlangUnknown::queryInterface(const SlangUUID &,void **)': is abstract
uint32_t ISlangUnknown::addRef(void)': is abstract
uint32_t ISlangUnknown::release(void)': is abstract
void *ISlangCastable::castAs(const SlangUUID &)': is abstract

Я нашел эти макросы, которые реализуют эти функции, но не знаю, как их использовать. (в slang/slang-com-helper.h)

SLANG_REF_OBJECT_IUNKNOWN_QUERY_INTERFACE;
SLANG_REF_OBJECT_IUNKNOWN_ADD_REF;
SLANG_REF_OBJECT_IUNKNOWN_RELEASE;

И у меня нет представления о том, как реализовать функцию castAs. Кто-нибудь знает, как я могу получить все подключения (рекурсивно), используемые данным шейдером slang?

Ответ или решение

В последней версии Vulkan SDK была добавлена поддержка языка шейдеров Slang, что открывает новые возможности для работы с графикой и разработкой шейдеров. Ваша задача заключается в программном использовании компилятора Slang из C++ кода с реализацией пользовательской файловой системы (ISlangFileSystem), чтобы вы могли отслеживать включения и перекомпилировать шейдеры во время выполнения. Ниже мы рассмотрим, как корректно реализовать интерфейс ISlangFileSystem, чтобы избежать ошибок компиляции и обеспечить функциональность, которую вы ищете.

Основные ошибки и их устранение

Ключевая проблема, с которой вы столкнулись, связана с тем, что класс FileSystem, реализующий интерфейс ISlangFileSystem, не реализует все обязательные виртуальные функции. Соответствующие ошибки говорят, что класс FileSystem не может быть инстанцирован, так как он является абстрактным классом.

Реализация интерфейса ISlangFileSystem

Для начала вам нужно реализовать все виртуальные функции интерфейса ISlangFileSystem. Это требует реализации методов для обработки управления памятью объектов, а также загрузки файлов. Используйте предоставленные макросы для упрощения этого процесса.

Вот пример реализации класса FileSystem:

#include "slang-com-helper.h" // Необходимо для работы с IUnknown

struct FileSystem : ISlangFileSystem {
    // Объект для отслеживания ссылок
    SLANG_REF_OBJECT_IUNKNOWN_QUERY_INTERFACE;
    SLANG_REF_OBJECT_IUNKNOWN_ADD_REF;
    SLANG_REF_OBJECT_IUNKNOWN_RELEASE;

    // Конструктор
    FileSystem() : refCount(1) {}

    // Метод для загрузки файлов
    virtual SlangResult loadFile(const char* path, ISlangBlob** outBlob) override {
        // Загрузка файла и создание нейросети ISlangBlob...
        // Примерный код для загрузки файла (замените на свою логику):
        FILE* file = fopen(path, "rb");
        if (!file) {
            return SLANG_FAIL; // Не удалось открыть файл
        }

        fseek(file, 0, SEEK_END);
        size_t size = ftell(file);
        fseek(file, 0, SEEK_SET);

        void* data = malloc(size);
        fread(data, 1, size, file);
        fclose(file);

        *outBlob = slang::createBlob(data, size);

        return SLANG_OK;
    }

    // Деструктор
    virtual ~FileSystem() {
        // Освобождение ресурсов, если требуется
    }

private:
    int refCount; // Счетчик ссылок для управления памятью
};

В этой реализации мы используем макросы для управления счетчиком ссылок и определения интерфейсов, необходимых для правильного функционирования IUnknown. Этот код прост и предназначен для загрузки файла, путем его открытия и считывания его содержимого.

Внедрение пользовательского файлового (файловой) системы в SlangCompiler

Ваша реализация SlangCompiler может оставаться в том виде, в котором она была, однако убедитесь, что вы корректно инициализируете и используете файловую систему:

struct SlangCompiler {
    slang::IGlobalSession* session = nullptr;
    slang::ICompileRequest* request = nullptr;
    FileSystem file_system;

    SlangCompiler() {
        SlangResult result;
        result = slang::createGlobalSession(&session);
        if (result != SLANG_OK) {
            // Обработка ошибки
            return;
        }

        result = session->createCompileRequest(&request);
        if (result != SLANG_OK) {
            // Обработка ошибки
            return;
        }

        request->setFileSystem(&file_system);
    }

    ~SlangCompiler() {
        if (request) {
            request->release();
            request = nullptr;
        }
        if (session) {
            session->release();
            session = nullptr;
        }
    }
};

Получение всех включений шейдера

Чтобы отслеживать все включаемые файлы (include) в шейдерах, вам потребуется дополнительно реализовать логику в методе loadFile, который будет извлекать из шейдеров директивы #include. Создайте обертку или дополнительную структуру, чтобы следить за ними. Например, вы можете хранить все включенные файлы в std::vector<std::string> includes внутри класса FileSystem и проверять наличие файла перед загрузкой.

Заключение

Соблюдая вышеописанные рекомендации, вы сможете успешно реализовать пользовательскую файловую систему для компиляции шейдеров на языке Slang. Правильная реализация интерфейса ISlangFileSystem позволит избежать ошибок компиляции и обеспечит возможность отслеживания и повторной компиляции шейдеров во время выполнения. Не забывайте тестировать и корректировать свою систему как на этапе загрузки файлов, так и на этапе обработки шейдеров.

Оцените материал
Добавить комментарий

Капча загружается...