Возможности семейства очереди передачи Vulkan и поддержка видеокарт: Точность проверки состояния? - PullRequest
0 голосов
/ 30 сентября 2018

Я следую этому видео-уроку Vulkan Youtube от Джошуа Шакера.Сейчас я работаю над его 14-м видео, где он работает над созданием семейства вторичных очередей для буфера вершин.Основное внимание уделяется процессу подготовки буферов вершин.Мой код совпадает с его кодом в его видео, за исключением кода cout statement, который я добавил для тестирования.Вот функция и структура семейства очередей:

struct QueueFamilyIndices {
    int graphicsFamily = -1;
    int transferFamily = -1;

    bool isComplete() {
        return (graphicsFamily >= 0 && transferFamily >= 0);
    }
};

QueueFamilyIndices FindQueueFamilies( const VkPhysicalDevice* device, const VkSurfaceKHR* surface ) {
    QueueFamilyIndices indices;
    uint32_t queueFamilyCount = 0;
    vkGetPhysicalDeviceQueueFamilyProperties( *device, &queueFamilyCount, nullptr );
    std::vector<VkQueueFamilyProperties> queueFamilies( queueFamilyCount );
    vkGetPhysicalDeviceQueueFamilyProperties( *device, &queueFamilyCount, queueFamilies.data() );

    int i = 0;
    for( const auto &queueFamily : queueFamilies ) {
        VkBool32 presentSupport = false;
        vkGetPhysicalDeviceSurfaceSupportKHR( *device, i, *surface, &presentSupport );

        if( queueFamily.queueCount > 0 && (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) && presentSupport ) {
            indices.graphicsFamily = i;
        }

        if( queueFamily.queueCount > 0 && (queueFamily.queueFlags & VK_QUEUE_TRANSFER_BIT) && 
            !(queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) && presentSupport ) {
            indices.transferFamily = i;
        }

        if( indices.isComplete() ) {
            break;
        }
        i++;
    }

    if( indices.graphicsFamily >= 0 && indices.transferFamily == -1 ) {
        std::cout << "Graphics family found, transfer family missing: using graphics family" << std::endl;
        indices.transferFamily = indices.graphicsFamily;
    }

    return indices;
}

Внутри этой функции vkGetPhysicalDeviceSurfaceSupportKHR(...) вызывается дважды, поскольку после вызова vkGetPhysicalDeviceQueueFamilyProperties(...) было найдено 2 семейства очередей для заполнениявектор VkQueueFamilyProperties структур.


Вот спецификации для моей карты NVidia GeForce gtx 750 Ti на основе спецификаций Vulkan's для ее семейств очередей: Vulkan: Report , и в случае, если ссылка меняется со временем,непосредственно информация:

Queue family                          0     
queueCount                            16 
flags                                 GRAPHICS_BIT
                                      COMPUTE_BIT
                                      TRANSFER_BIT
                                      SPARSE_BINDING_BIT 
timestampValidBits                    64 
minImageTransferGranularity.width     1 
minImageTransferGranularity.height    1
minImageTransferGranularity.depth     1 
supportsPresent                       1 

Queue family                          1 
queueCount                            1 
flags                                 TRANSFER_BIT
timestampValidBits                    64 
minImageTransferGranularity.width     1 
minImageTransferGranularity.height    1 
minImageTransferGranularity.depth     1 
supportsPresent                       0 

Теперь согласно этим спецификациям, которые совпадают со значениями в моем векторе структур, пока я прохожу через отладчик, мои структуры заполняются значениями:

 queueFamilies[0].queueFlags = 15;
 queueFamilies[0].queueCount = 16;
 queueFamilies[0].timestampValidBits = 64;
 queueFamilies[0].minImageTransferGranularity = { width = 1, height = 1, depth = 1 };

 queueFamilies[1].queueFlags = 4;
 queueFamilies[1].queueCount = 1;
 queueFamilies[1].timestampValidBits = 64;
 queueFamilies[1].minImageTransferGranularity = { width = 1, height = 1, depth = 1 };

Так что мне кажется, что моя карта поддерживает отдельный queueFamily, в частности transferFamily.


Исходя из моего предположения об этой поддержке и пошагового выполнения этой функции, у него есть два оператора if для проверки допустимых условий в цикле for для каждого из проиндексированных queueFamily объектов.Операторы if возвращаются именно так, как они должны быть.Мой код компилируется и собирается без каких-либо ошибок или предупреждений, и он по-прежнему отображает треугольник, когда я не запускаю его через отладчик, и он завершается с кодом (0).Таким образом, код, кажется, в порядке.Однако я не получаю результатов, которых я бы, по крайней мере, ожидал.

Я не уверен, есть ли в его коде ошибка, которую он случайно пропустил, неправильно ли я понимаю, что моя видеокарта поддерживает эту функциональность Vulkan, или это может быть либо ошибка Vulkan API, либоОшибка драйвера NVidia.

Однако, когда я проходил через эту функцию, выяснял, почему переменная indices.transferFamily не была установлена ​​в i;Я заметил, что на второй итерации цикла это не имеет ничего общего с наличием transferFamilyQueue, его значений параметров или флагов.Причиной этого, если оператор возвращает false, является переменная presentSupport, так как она устанавливается на 0 при втором вызове, который соответствует приведенной выше таблице данных.Таким образом, результат будет таким, как ожидалось.

Тогда возникает мой вопрос: существует ли реальная проблема реализации с проверкой условия во втором операторе if?

Здесь яЯ застрял, потому что я немного запутался, потому что мы проверяем, есть ли доступный transferQueueFamily, и если да, то используем его для создания и stagingBuffer, чтобы скопировать содержимое из CPU в GPU для vertex buffer(s).Из того, что я вижу, похоже, что у моей карты есть transferFamily, но нет supportPresent для этой семьи.Однако, когда думаешь об этом;если вы используете transferFamily - transferQueue, вы не захотите present напрямую, поскольку вы просто будете копировать данные из временного vertexBuffer на ЦП в vertexBuffer, который будет использоватьсяна ГПУ.Так что мне интересно, если окончательная проверка в этом, если утверждение является правильным или нет.Если мои предположения о том, как Vulkan работает здесь, неверны, пожалуйста, не стесняйтесь меня поправлять, так как это моя первая попытка заставить работать приложение рендеринга Vulkan.

Ответы [ 3 ]

0 голосов
/ 30 сентября 2018

Нет ошибок Vulkan API или NVidia Driver.Это прямо в вашем отчете:

supportsPresent 0

Например, AMD, похоже, поддерживает подарки в VK_QUEUE_TRANSFER_BIT семействах очередей, но это не обязательно (31.4Запрос поддержки WSI):

Не все физические устройства будут поддерживать WSI.Внутри физического устройства не все семейства очередей будут поддерживать представление.

0 голосов
/ 30 сентября 2018

Прочитав несколько хороших ответов здесь и выполнив еще несколько тестов с моей стороны, я думаю, что нашел подходящее решение для разработки кода приложения.Эта функция вызывается примерно 4 или 5 раз по всему приложению другими функциями.Он вызывается, когда Vulkan инициализируется, он вызывается снова, когда оценивается пригодность устройств для выбора наилучшего из доступных устройств, он также вызывается при создании логического устройства и так далее.

Все эти начальные вызовы обычно нуждаются только в значениях счетчика и / или индекса queueFamily's, чтобы убедиться, что подходящее графическое устройство с queueFamily доступно для обработки и рендеринга графики.

Однако, когда эта функция вызывается для создания произвольного буфера, который будет использоваться в качестве промежуточного буфера для существующей выделенной очереди передачи, на этот раз нам фактически потребуется очередь семейства и все ее свойства.Итак, чтобы исправить эту проблему;при проверке graphicsQueue я оставил эту последнюю проверку условий, чтобы проверить, доступна ли presentSupport, поскольку, когда цикл for выполняет итерации к следующему индексу для проверки выделенного transferQueue, я пропустил эту проверку условий для presentSupport все вместе.

QueueFamilyIndices FindQueueFamilies( const VkPhysicalDevice* device, const VkSurfaceKHR* surface ) {
    QueueFamilyIndices indices;
    uint32_t queueFamilyCount = 0;
    vkGetPhysicalDeviceQueueFamilyProperties( *device, &queueFamilyCount, nullptr );
    std::vector<VkQueueFamilyProperties> queueFamilies( queueFamilyCount );
    vkGetPhysicalDeviceQueueFamilyProperties( *device, &queueFamilyCount, queueFamilies.data() );

    int i = 0;
    for( const auto &queueFamily : queueFamilies ) {
        VkBool32 presentSupport = false;
        vkGetPhysicalDeviceSurfaceSupportKHR( *device, i, *surface, &presentSupport );

        if( queueFamily.queueCount > 0 && (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) && presentSupport ) {
            indices.graphicsFamily = i;
        }

        if( queueFamily.queueCount > 0 && (queueFamily.queueFlags & VK_QUEUE_TRANSFER_BIT) && 
            !(queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) /*&& presentSupport*/ ) {
            indices.transferFamily = i;
        }

        if( indices.isComplete() ) {
            break;
        }
        i++;
    }

    if( indices.graphicsFamily >= 0 && indices.transferFamily == -1 ) {
        std::cout << "Graphics family found, transfer family missing: using graphics family" << std::endl;
        indices.transferFamily = indices.graphicsFamily;
    }

    return indices;
}

Теперь indices.transferFamily не только устанавливается на i на итерации 2 и ;проверка для indices.isComplete() также возвращает значение true, а последний оператор if для отката теперь возвращает значение false.Кажется, что все правильно рендерится без проблем.Похоже, что staging buffers теперь копируется в GPU вместо использования CPU для vertex buffer объектов.

0 голосов
/ 30 сентября 2018

Нет веских причин для проверки presentSupport при поиске определенной очереди передачи.Вероятно, это ошибка копирования и вставки где-то .Как правило, вам все равно, поддерживает ли презентация что-либо, кроме графической очереди.

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

...