Я следую этому видео-уроку 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
.