I am following this Vulkan Youtube video tutorial by Joshua Shucker. I'm currently on his 14th video where he is working on creating a secondary queue family for the vertex buffer. My code matches that of his in his video except that of a cout statement
in which I added for testing. Here is the function:
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;
}
Within this function vkGetPhysicalDeviceSurfaceSupportKHR(...)
is being called twice as there have been 2 queue families found after vkGetPhysicalDeviceQueueFamilyProperties(...)
has been called to populate the vector of VkQueueFamilyProperties
structures. Here is the specs for my NVidia GeForce gtx 750 Ti
card based on Vulkan's
specifications for its queue families: Vulkan:Report and in case the link changes over time here is the information directly:
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
Now according to these specs which coincide with the values in my vector of structs while I'm stepping through the debugger my structures are populated with the values of:
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 };
So this appears to me that my card does support a separate queueFamily
specifically the transferFamily
.
Based on my assumption of this support and stepping through this function he has two if statements to check for valid conditions within the for loop for each of the indexed queueFamily
objects. The if statements are returning exactly as they should be. My code compiles and builds without any errors or warnings, and it still does render then triangle when I'm not running it through the debugger and it does exit with a code of (0). So the code appears to be fine. However I'm not getting the results that I would at least be expecting.
I'm not sure if there is a bug in his code that he happened to missed, if I'm misinterpreting my video card's support of this Vulkan functionality, or if this could be either a Vulkan API bug or NVidia Driver bug.
However as I was stepping through this function to find out why the indices.transferFamily
variable was not being set to i
on the second iteration of the loop has nothing to do with the presence of the transferFamilyQueue
, its parameter values or flags. What is causing this if statement to return false is the presentSupport
variable as it is being set to 0
on the second call which does match the data sheet above. So the output is as expected.
My question them becomes: is there an actual implementation problem with the condition checking in the second if statement?
This is where I'm stuck as I am a bit confused because we are checking to see if there is a transferQueueFamily
available and if so use that to create and use a stagingBuffer
to copy the contents from the CPU to the GPU for the vertex buffer(s)
. From what I can see it appears my card does have this transferFamily
but does not have supportPresent
for this family. However, when thinking about it; if you are using a transferFamily
- transferQueue
you wouldn't want to present
it directly as you'll just be copying the data from a temporary vertexBuffer
on the CPU to the vertexBuffer
that will be used on the GPU. So I'm wondering if the final check in this if statement is correct or not. If my assumptions about how Vulkan is working here is incorrect please don't hesitate to correct me as this is my first attempt and getting a rendering application of Vulkan
working.
Aucun commentaire:
Enregistrer un commentaire