C++ Vulkan';s传输队列系列功能和视频卡支持:条件检查是否准确?
下面是Joshua Shucker的文章。我现在正在看他的第14个视频,他正在为顶点缓冲区创建一个辅助队列族。本文重点介绍顶点缓冲区的暂存过程。我的代码与他的视频中的代码相匹配,除了我添加用于测试的C++ Vulkan';s传输队列系列功能和视频卡支持:条件检查是否准确?,c++,specifications,vulkan,C++,Specifications,Vulkan,下面是Joshua Shucker的文章。我现在正在看他的第14个视频,他正在为顶点缓冲区创建一个辅助队列族。本文重点介绍顶点缓冲区的暂存过程。我的代码与他的视频中的代码相匹配,除了我添加用于测试的cout语句的代码。以下是队列族的功能和结构: struct QueueFamilyIndices { int graphicsFamily = -1; int transferFamily = -1; bool isComplete() { return (
cout语句的代码。以下是队列族的功能和结构:
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;
}
现在,根据这些规范,当我通过调试器时,这些规范与我的结构向量中的值一致,我的结构被填充
以下各项的价值:
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)退出。所以代码看起来很好。然而,我没有得到我至少预期的结果
我不确定他的代码中是否有他碰巧漏掉的bug,我是否误解了我的视频卡对Vulkan功能的支持,或者这可能是Vulkan API bug或NVidia驱动程序bug
但是,当我单步执行此函数以找出index.transferFamily
变量未设置为I
的原因时;我注意到,在循环的第二次迭代中,它与transferFamilyQueue
的存在、其参数值或标志无关。导致此if语句返回false的原因是presentSupport
变量,因为在第二次调用时它被设置为0
,这与上面的数据表匹配。因此,输出与预期一致
我的问题是:第二个if语句中的条件检查是否存在实际的实现问题
这就是我被卡住的地方,因为我有点困惑,因为我们正在检查是否有可用的transferQueueFamily
,如果有,则使用它创建并使用stagingBuffer
将内容从CPU复制到顶点缓冲区的GPU
。从我所看到的情况来看,我的卡似乎有此transferFamily
,但没有此家族的supportPresent
。但是,想起来,;如果您使用的是transferFamily
-transferQueue
您不想直接显示它,因为您只需要将数据从CPU上的临时vertexBuffer
复制到GPU上使用的vertexBuffer
。所以我想知道这个if语句中的最终检查是否正确。如果我对Vulkan如何工作的假设不正确,请毫不犹豫地纠正我,因为这是我第一次尝试让Vulkan
渲染应用程序工作 在搜索特定于换乘的队列时,没有很好的理由检查presentSupport
。这可能是某个地方的复制粘贴错误。通常,您不关心图形队列以外的任何东西是否支持表示
您确实希望使用未设置图形位的传输队列,因为这样的队列可能对应于专用传输硬件,不会影响在图形队列上完成的工作的性能 在搜索特定于换乘的队列时,没有很好的理由检查presentSupport
。这可能是某个地方的复制粘贴错误。通常,您不关心图形队列以外的任何东西是否支持表示
您确实希望使用未设置图形位的传输队列,因为这样的队列可能对应于专用传输硬件,不会影响在图形队列上完成的工作的性能 没有Vulkan API或NVidia驱动程序错误。就在你的报告单上:
支持当前0
例如,AMD似乎确实支持VK\u QUEUE\u TRANSFER\u BIT
队列系列上的显示,但它是纯可选的(31.4.查询WSI支持):
并非所有物理设备都将包括WSI支持。在物理设备中,并非所有队列族都支持表示
没有Vulkan API或NVidia驱动程序错误。就在你的报告单上:
支持当前0
例如,AMD似乎确实支持VK\u QUEUE\u TRANSFER\u BIT
队列系列上的显示,但它是纯可选的(31.4.查询WSI支持):
并非所有物理设备都将包括WSI支持。在物理设备中,并非所有队列族都支持表示
在阅读了这里的一些好的答案并在我这方面做了更多的测试之后,我认为我已经找到了应用程序代码设计的适当解决方案。此函数在整个应用程序中被其他函数调用大约4或5次。当初始化Vulkan
时调用,当评估设备是否适合选择可用的最佳设备时再次调用,在创建逻辑设备时也会调用,等等
所有这些初始调用通常只需要queueFamily的
计数和/或索引值,以确保具有queueFamily
的适当图形设备可用于图形处理和渲染<
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 };
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;
}