in renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp [1673:4147]
bool WrappedVulkan::Serialise_vkCreateDevice(SerialiserType &ser, VkPhysicalDevice physicalDevice,
const VkDeviceCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkDevice *pDevice)
{
SERIALISE_ELEMENT(physicalDevice).Important();
SERIALISE_ELEMENT_LOCAL(CreateInfo, *pCreateInfo).Important();
SERIALISE_ELEMENT_OPT(pAllocator);
SERIALISE_ELEMENT_LOCAL(Device, GetResID(*pDevice)).TypedAs("VkDevice"_lit);
if(ser.VersionLess(0xD))
{
uint32_t supportedQueueFamily; // no longer used
SERIALISE_ELEMENT(supportedQueueFamily).Hidden();
}
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
// kept around only to call DerivedResource below, as this is the resource that actually has an
// original resource ID.
VkPhysicalDevice origPhysDevice = physicalDevice;
// see above in Serialise_vkEnumeratePhysicalDevices where this is encoded
uint32_t physicalDeviceIndex = GetPhysicalDeviceIndexFromHandle(Unwrap(physicalDevice));
physicalDevice = m_PhysicalDevices[physicalDeviceIndex];
RDCLOG("Creating replay device from physical device %u", physicalDeviceIndex);
ObjDisp(physicalDevice)
->GetPhysicalDeviceProperties(Unwrap(physicalDevice), &m_PhysicalDeviceData.props);
ObjDisp(physicalDevice)
->GetPhysicalDeviceMemoryProperties(Unwrap(physicalDevice), &m_PhysicalDeviceData.memProps);
ObjDisp(physicalDevice)
->GetPhysicalDeviceFeatures(Unwrap(physicalDevice), &m_PhysicalDeviceData.availFeatures);
GetPhysicalDeviceDriverProperties(ObjDisp(physicalDevice), Unwrap(physicalDevice),
m_PhysicalDeviceData.driverProps);
m_PhysicalDeviceData.driverInfo =
VkDriverInfo(m_PhysicalDeviceData.props, m_PhysicalDeviceData.driverProps, true);
rdcarray<VkDeviceQueueGlobalPriorityCreateInfoKHR *> queuePriorities;
for(uint32_t i = 0; i < CreateInfo.queueCreateInfoCount; i++)
{
VkDeviceQueueGlobalPriorityCreateInfoKHR *queuePrio =
(VkDeviceQueueGlobalPriorityCreateInfoKHR *)FindNextStruct(
&CreateInfo.pQueueCreateInfos[i],
VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_KHR);
if(queuePrio)
queuePriorities.push_back(queuePrio);
}
const PhysicalDeviceData &origData = m_OriginalPhysicalDevices[physicalDeviceIndex];
m_OrigPhysicalDeviceData = origData;
m_OrigPhysicalDeviceData.driverInfo = VkDriverInfo(origData.props, origData.driverProps, false);
// we must make any modifications locally, so the free of pointers
// in the serialised VkDeviceCreateInfo don't double-free
VkDeviceCreateInfo createInfo = CreateInfo;
rdcarray<rdcstr> Extensions;
for(uint32_t i = 0; i < createInfo.enabledExtensionCount; i++)
{
Extensions.push_back(createInfo.ppEnabledExtensionNames[i]);
}
StripUnwantedExtensions(Extensions);
std::set<rdcstr> supportedExtensions;
{
uint32_t count = 0;
ObjDisp(physicalDevice)
->EnumerateDeviceExtensionProperties(Unwrap(physicalDevice), NULL, &count, NULL);
VkExtensionProperties *props = new VkExtensionProperties[count];
ObjDisp(physicalDevice)
->EnumerateDeviceExtensionProperties(Unwrap(physicalDevice), NULL, &count, props);
for(uint32_t e = 0; e < count; e++)
supportedExtensions.insert(props[e].extensionName);
SAFE_DELETE_ARRAY(props);
}
AddRequiredExtensions(false, Extensions, supportedExtensions);
// Drop VK_KHR_driver_properties if it's not available, but add it if it is
bool driverPropsSupported = (supportedExtensions.find(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME) !=
supportedExtensions.end());
if(driverPropsSupported)
{
if(!Extensions.contains(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME))
Extensions.push_back(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME);
}
else
{
Extensions.removeOne(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME);
}
for(size_t i = 0; i < Extensions.size(); i++)
{
if(supportedExtensions.find(Extensions[i]) == supportedExtensions.end())
{
SET_ERROR_RESULT(m_FailedReplayResult, ResultCode::APIHardwareUnsupported,
"Capture requires extension '%s' which is not supported\n"
"\n%s",
Extensions[i].c_str(), GetPhysDeviceCompatString(false, false).c_str());
return false;
}
}
// enable VK_EXT_debug_marker if it's available, to replay markers to the driver/any other
// layers that might be listening
if(supportedExtensions.find(VK_EXT_DEBUG_MARKER_EXTENSION_NAME) != supportedExtensions.end())
{
Extensions.push_back(VK_EXT_DEBUG_MARKER_EXTENSION_NAME);
RDCLOG("Enabling VK_EXT_debug_marker");
}
// enable VK_AMD_SHADER_INFO_EXTENSION_NAME if it's available, to fetch shader disassembly
if(supportedExtensions.find(VK_AMD_SHADER_INFO_EXTENSION_NAME) != supportedExtensions.end())
{
Extensions.push_back(VK_AMD_SHADER_INFO_EXTENSION_NAME);
RDCLOG("Enabling VK_AMD_shader_info");
}
// enable VK_AMD_gpa_interface if it's available, for AMD counter support
if(supportedExtensions.find("VK_AMD_gpa_interface") != supportedExtensions.end())
{
Extensions.push_back("VK_AMD_gpa_interface");
RDCLOG("Enabling VK_AMD_gpa_interface");
}
// enable VK_AMD_shader_core_properties if it's available, for AMD counter support
if(supportedExtensions.find(VK_AMD_SHADER_CORE_PROPERTIES_EXTENSION_NAME) !=
supportedExtensions.end())
{
Extensions.push_back(VK_AMD_SHADER_CORE_PROPERTIES_EXTENSION_NAME);
RDCLOG("Enabling VK_AMD_shader_core_properties");
}
// enable VK_MVK_moltenvk if it's available, for detecting/controlling moltenvk.
// Currently this is used opaquely (extension present or not) rather than using anything the
// extension provides.
if(supportedExtensions.find("VK_MVK_moltenvk") != supportedExtensions.end())
{
Extensions.push_back("VK_MVK_moltenvk");
RDCLOG("Enabling VK_MVK_moltenvk");
}
// enable VK_KHR_driver_properties if it's available, to match up to capture-time
if(supportedExtensions.find(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME) != supportedExtensions.end())
{
Extensions.push_back(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME);
RDCLOG("Enabling VK_KHR_driver_properties");
}
// enable VK_KHR_shader_non_semantic_info if it's available, to enable debug printf
if(supportedExtensions.find(VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME) !=
supportedExtensions.end())
{
Extensions.push_back(VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME);
RDCLOG("Enabling VK_KHR_shader_non_semantic_info");
}
bool pipeExec = false;
// enable VK_KHR_pipeline_executable_properties if it's available, to fetch disassembly and
// statistics
if(supportedExtensions.find(VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME) !=
supportedExtensions.end())
{
pipeExec = true;
Extensions.push_back(VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME);
RDCLOG("Enabling VK_KHR_pipeline_executable_properties");
}
bool xfb = false;
// enable VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME if it's available, to fetch mesh output in
// tessellation/geometry stages
if(supportedExtensions.find(VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME) != supportedExtensions.end())
{
xfb = true;
Extensions.push_back(VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME);
RDCLOG("Enabling VK_EXT_transform_feedback extension");
}
else
{
RDCWARN(
"VK_EXT_transform_feedback extension not available, mesh output from "
"geometry/tessellation stages will not be available");
}
bool scalarBlock = false;
// enable VK_EXT_scalar_block_layout if it's available, to fetch mesh output in the mesh stage
if(supportedExtensions.find(VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME) !=
supportedExtensions.end())
{
scalarBlock = true;
Extensions.push_back(VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME);
RDCLOG("Enabling VK_EXT_scalar_block_layout extension");
}
else
{
VkPhysicalDeviceMeshShaderFeaturesEXT *meshFeats =
(VkPhysicalDeviceMeshShaderFeaturesEXT *)FindNextStruct(
&createInfo, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT);
if(meshFeats && meshFeats->meshShader)
RDCWARN(
"VK_EXT_scalar_block_layout extension not available, mesh output from "
"mesh stage will not be available");
}
bool KHRbuffer = false, EXTbuffer = false;
if(supportedExtensions.find(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME) !=
supportedExtensions.end())
{
Extensions.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
RDCLOG("Enabling VK_KHR_buffer_device_address");
KHRbuffer = true;
}
else if(supportedExtensions.find(VK_EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME) !=
supportedExtensions.end())
{
Extensions.push_back(VK_EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
RDCLOG("Enabling VK_EXT_buffer_device_address");
EXTbuffer = true;
}
else
{
RDCWARN(
"VK_[KHR|EXT]_buffer_device_address not available, feedback from "
"bindless shader access will use less reliable fallback");
}
bool perfQuery = false;
if(supportedExtensions.find(VK_KHR_PERFORMANCE_QUERY_EXTENSION_NAME) != supportedExtensions.end())
{
perfQuery = true;
Extensions.push_back(VK_KHR_PERFORMANCE_QUERY_EXTENSION_NAME);
RDCLOG("Enabling VK_KHR_performance_query");
}
VkDevice device;
rdcarray<VkQueueFamilyProperties> queueProps;
{
uint32_t qCount = 0;
ObjDisp(physicalDevice)
->GetPhysicalDeviceQueueFamilyProperties(Unwrap(physicalDevice), &qCount, NULL);
queueProps.resize(qCount);
ObjDisp(physicalDevice)
->GetPhysicalDeviceQueueFamilyProperties(Unwrap(physicalDevice), &qCount,
queueProps.data());
}
// to aid the search algorithm below, we apply implied transfer bit onto the queue properties.
for(VkQueueFamilyProperties &q : queueProps)
{
if(q.queueFlags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT))
q.queueFlags |= VK_QUEUE_TRANSFER_BIT;
}
uint32_t origQCount = origData.queueCount;
const VkQueueFamilyProperties *origprops = origData.queueProps;
// create queue remapping
for(uint32_t origQIndex = 0; origQIndex < origQCount; origQIndex++)
{
m_QueueRemapping[origQIndex].resize(origprops[origQIndex].queueCount);
RDCLOG("Capture describes queue family %u:", origQIndex);
RDCLOG(" - %u queues available with %s", origprops[origQIndex].queueCount,
ToStr(VkQueueFlagBits(origprops[origQIndex].queueFlags)).c_str());
RDCLOG(" %u timestamp bits (%u,%u,%u) granularity",
origprops[origQIndex].timestampValidBits,
origprops[origQIndex].minImageTransferGranularity.width,
origprops[origQIndex].minImageTransferGranularity.height,
origprops[origQIndex].minImageTransferGranularity.depth);
// find the best queue family to map to. We try and find the closest match that is at least
// good enough. We want to try and preserve families that were separate before but we need to
// ensure the remapped queue family is at least as good as it was at capture time.
uint32_t destFamily = 0;
if(origQIndex < queueProps.size() && equivalent(origprops[origQIndex], queueProps[origQIndex]))
{
destFamily = origQIndex;
RDCLOG(" (identity match)");
}
else
{
// we categorise the original queue as one of four types: universal
// (graphics/compute/transfer), graphics/transfer only (rare), compute-only
// (compute/transfer) or transfer-only (transfer). We try first to find an exact match, then
// move progressively up the priority list to find a broader and broader match.
// We don't care about sparse binding - it's just treated as a requirement.
enum class SearchType
{
Other,
Universal,
GraphicsTransfer,
ComputeTransfer,
GraphicsOrComputeTransfer,
TransferOnly,
} search;
VkQueueFlags mask = (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT);
switch(origprops[origQIndex].queueFlags & mask)
{
case VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT:
case VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT:
search = SearchType::Universal;
break;
case VK_QUEUE_GRAPHICS_BIT:
case VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_TRANSFER_BIT:
search = SearchType::GraphicsTransfer;
break;
case VK_QUEUE_COMPUTE_BIT:
case VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT:
search = SearchType::ComputeTransfer;
break;
case VK_QUEUE_TRANSFER_BIT: search = SearchType::TransferOnly; break;
default:
search = SearchType::Other;
// video queue, NV optical flow, some type of queue we don't handle
break;
}
bool needSparse = (origprops[origQIndex].queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) != 0;
VkExtent3D needGranularity = origprops[origQIndex].minImageTransferGranularity;
while(search != SearchType::Other)
{
bool found = false;
for(uint32_t replayQIndex = 0; replayQIndex < queueProps.size(); replayQIndex++)
{
// ignore queues that couldn't satisfy the required transfer granularity
if(!CheckTransferGranularity(needGranularity,
queueProps[replayQIndex].minImageTransferGranularity))
continue;
// ignore queues that don't have sparse binding, if we need that
if(needSparse &&
((queueProps[replayQIndex].queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) == 0))
continue;
switch(search)
{
case SearchType::Other: break;
case SearchType::Universal:
if((queueProps[replayQIndex].queueFlags & mask) ==
(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT))
{
destFamily = replayQIndex;
found = true;
}
break;
case SearchType::GraphicsTransfer:
if((queueProps[replayQIndex].queueFlags & mask) ==
(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_TRANSFER_BIT))
{
destFamily = replayQIndex;
found = true;
}
break;
case SearchType::ComputeTransfer:
if((queueProps[replayQIndex].queueFlags & mask) ==
(VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT))
{
destFamily = replayQIndex;
found = true;
}
break;
case SearchType::GraphicsOrComputeTransfer:
if((queueProps[replayQIndex].queueFlags & mask) ==
(VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT) ||
(queueProps[replayQIndex].queueFlags & mask) ==
(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_TRANSFER_BIT))
{
destFamily = replayQIndex;
found = true;
}
break;
case SearchType::TransferOnly:
if((queueProps[replayQIndex].queueFlags & mask) == VK_QUEUE_TRANSFER_BIT)
{
destFamily = replayQIndex;
found = true;
}
break;
}
if(found)
break;
}
if(found)
break;
// no such queue family found, fall back to the next type of queue to search for
switch(search)
{
case SearchType::Other: break;
case SearchType::Universal: search = SearchType::Other; break;
case SearchType::GraphicsTransfer:
case SearchType::ComputeTransfer:
case SearchType::GraphicsOrComputeTransfer:
// if we didn't find a graphics or compute (and transfer) queue, we have to look for a
// universal one
search = SearchType::Universal;
break;
case SearchType::TransferOnly:
// when falling back from looking for a transfer-only queue, we consider either
// graphics-only or compute-only as better candidates before universal
search = SearchType::GraphicsOrComputeTransfer;
break;
}
}
}
RDCLOG("Remapping to queue family %u:", destFamily);
RDCLOG(" - %u queues available with %s", queueProps[destFamily].queueCount,
ToStr(VkQueueFlagBits(queueProps[destFamily].queueFlags)).c_str());
RDCLOG(" %u timestamp bits (%u,%u,%u) granularity",
queueProps[destFamily].timestampValidBits,
queueProps[destFamily].minImageTransferGranularity.width,
queueProps[destFamily].minImageTransferGranularity.height,
queueProps[destFamily].minImageTransferGranularity.depth);
// loop over the queues, wrapping around if necessary to provide enough queues. The idea being
// an application is more likely to use early queues than later ones, so if there aren't
// enough queues in the family then we should prioritise giving unique queues to the early
// indices
for(uint32_t q = 0; q < origprops[origQIndex].queueCount; q++)
{
m_QueueRemapping[origQIndex][q] = {destFamily, q % queueProps[destFamily].queueCount};
}
}
VkDeviceQueueCreateInfo *queueCreateInfos =
(VkDeviceQueueCreateInfo *)createInfo.pQueueCreateInfos;
// now apply the remapping to the requested queues
for(uint32_t i = 0; i < createInfo.queueCreateInfoCount; i++)
{
VkDeviceQueueCreateInfo &queueCreate = (VkDeviceQueueCreateInfo &)queueCreateInfos[i];
uint32_t queueFamily = queueCreate.queueFamilyIndex;
queueFamily = m_QueueRemapping[queueFamily][0].family;
queueCreate.queueFamilyIndex = queueFamily;
uint32_t queueCount = RDCMIN(queueCreate.queueCount, queueProps[queueFamily].queueCount);
if(queueCount < queueCreate.queueCount)
RDCWARN("Truncating queue family request from %u queues to %u queues",
queueCreate.queueCount, queueCount);
queueCreate.queueCount = queueCount;
}
// remove any duplicates that have been created
rdcarray<VkDeviceQueueCreateInfo> queueInfos;
for(uint32_t i = 0; i < createInfo.queueCreateInfoCount; i++)
{
VkDeviceQueueCreateInfo &queue1 = (VkDeviceQueueCreateInfo &)queueCreateInfos[i];
// if we already have this one in the list, continue
bool already = false;
for(const VkDeviceQueueCreateInfo &queue2 : queueInfos)
{
if(queue1.queueFamilyIndex == queue2.queueFamilyIndex)
{
already = true;
break;
}
}
if(already)
continue;
// get the 'biggest' queue allocation from all duplicates. That way we ensure we have enough
// queues in the queue family to satisfy any remap.
VkDeviceQueueCreateInfo biggest = queue1;
for(uint32_t j = i + 1; j < createInfo.queueCreateInfoCount; j++)
{
VkDeviceQueueCreateInfo &queue2 = (VkDeviceQueueCreateInfo &)queueCreateInfos[j];
if(biggest.queueFamilyIndex == queue2.queueFamilyIndex)
{
if(queue2.queueCount > biggest.queueCount)
biggest = queue2;
}
}
queueInfos.push_back(biggest);
}
createInfo.queueCreateInfoCount = (uint32_t)queueInfos.size();
createInfo.pQueueCreateInfos = queueInfos.data();
uint32_t qFamilyIdx = 0;
if(!SelectGraphicsComputeQueue(queueProps, createInfo, qFamilyIdx))
{
SET_ERROR_RESULT(
m_FailedReplayResult, ResultCode::APIHardwareUnsupported,
"Can't add a queue with required properties for RenderDoc! Unsupported configuration");
return false;
}
// remove structs from extensions that we have stripped but may still be referenced here,
// to ensure we don't pass structs for disabled extensions.
bool private_data = false;
private_data |= RemoveNextStruct(&createInfo, VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO);
private_data |=
RemoveNextStruct(&createInfo, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES);
if(private_data)
{
RDCLOG("Removed VK_EXT_private_data structs from vkCreateDevice pNext chain");
}
bool present_id = false;
present_id |=
RemoveNextStruct(&createInfo, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR);
present_id |=
RemoveNextStruct(&createInfo, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_WAIT_FEATURES_KHR);
if(present_id)
{
RDCLOG("Removed VK_KHR_present_id/wait structs from vkCreateDevice pNext chain");
}
VkPhysicalDeviceFeatures enabledFeatures = {0};
if(createInfo.pEnabledFeatures != NULL)
enabledFeatures = *createInfo.pEnabledFeatures;
VkPhysicalDeviceFeatures2 *enabledFeatures2 = (VkPhysicalDeviceFeatures2 *)FindNextStruct(
&createInfo, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2);
// VkPhysicalDeviceFeatures2 takes priority
if(enabledFeatures2)
enabledFeatures = enabledFeatures2->features;
else if(createInfo.pEnabledFeatures)
enabledFeatures = *createInfo.pEnabledFeatures;
VkPhysicalDeviceFeatures availFeatures = {0};
ObjDisp(physicalDevice)->GetPhysicalDeviceFeatures(Unwrap(physicalDevice), &availFeatures);
#define CHECK_PHYS_FEATURE(feature) \
if(enabledFeatures.feature && !availFeatures.feature) \
{ \
SET_ERROR_RESULT(m_FailedReplayResult, ResultCode::APIHardwareUnsupported, \
"Capture requires physical device feature '" #feature \
"' which is not supported\n\n%s", \
GetPhysDeviceCompatString(false, false).c_str()); \
return false; \
}
CHECK_PHYS_FEATURE(robustBufferAccess);
CHECK_PHYS_FEATURE(fullDrawIndexUint32);
CHECK_PHYS_FEATURE(imageCubeArray);
CHECK_PHYS_FEATURE(independentBlend);
CHECK_PHYS_FEATURE(geometryShader);
CHECK_PHYS_FEATURE(tessellationShader);
CHECK_PHYS_FEATURE(sampleRateShading);
CHECK_PHYS_FEATURE(dualSrcBlend);
CHECK_PHYS_FEATURE(logicOp);
CHECK_PHYS_FEATURE(multiDrawIndirect);
CHECK_PHYS_FEATURE(drawIndirectFirstInstance);
CHECK_PHYS_FEATURE(depthClamp);
CHECK_PHYS_FEATURE(depthBiasClamp);
CHECK_PHYS_FEATURE(fillModeNonSolid);
CHECK_PHYS_FEATURE(depthBounds);
CHECK_PHYS_FEATURE(wideLines);
CHECK_PHYS_FEATURE(largePoints);
CHECK_PHYS_FEATURE(alphaToOne);
CHECK_PHYS_FEATURE(multiViewport);
CHECK_PHYS_FEATURE(samplerAnisotropy);
CHECK_PHYS_FEATURE(textureCompressionETC2);
CHECK_PHYS_FEATURE(textureCompressionASTC_LDR);
CHECK_PHYS_FEATURE(textureCompressionBC);
CHECK_PHYS_FEATURE(occlusionQueryPrecise);
CHECK_PHYS_FEATURE(pipelineStatisticsQuery);
CHECK_PHYS_FEATURE(vertexPipelineStoresAndAtomics);
CHECK_PHYS_FEATURE(fragmentStoresAndAtomics);
CHECK_PHYS_FEATURE(shaderTessellationAndGeometryPointSize);
CHECK_PHYS_FEATURE(shaderImageGatherExtended);
CHECK_PHYS_FEATURE(shaderStorageImageExtendedFormats);
CHECK_PHYS_FEATURE(shaderStorageImageMultisample);
CHECK_PHYS_FEATURE(shaderStorageImageReadWithoutFormat);
CHECK_PHYS_FEATURE(shaderStorageImageWriteWithoutFormat);
CHECK_PHYS_FEATURE(shaderUniformBufferArrayDynamicIndexing);
CHECK_PHYS_FEATURE(shaderSampledImageArrayDynamicIndexing);
CHECK_PHYS_FEATURE(shaderStorageBufferArrayDynamicIndexing);
CHECK_PHYS_FEATURE(shaderStorageImageArrayDynamicIndexing);
CHECK_PHYS_FEATURE(shaderClipDistance);
CHECK_PHYS_FEATURE(shaderCullDistance);
CHECK_PHYS_FEATURE(shaderFloat64);
CHECK_PHYS_FEATURE(shaderInt64);
CHECK_PHYS_FEATURE(shaderInt16);
CHECK_PHYS_FEATURE(shaderResourceResidency);
CHECK_PHYS_FEATURE(shaderResourceMinLod);
CHECK_PHYS_FEATURE(sparseBinding);
CHECK_PHYS_FEATURE(sparseResidencyBuffer);
CHECK_PHYS_FEATURE(sparseResidencyImage2D);
CHECK_PHYS_FEATURE(sparseResidencyImage3D);
CHECK_PHYS_FEATURE(sparseResidency2Samples);
CHECK_PHYS_FEATURE(sparseResidency4Samples);
CHECK_PHYS_FEATURE(sparseResidency8Samples);
CHECK_PHYS_FEATURE(sparseResidency16Samples);
CHECK_PHYS_FEATURE(sparseResidencyAliased);
CHECK_PHYS_FEATURE(variableMultisampleRate);
CHECK_PHYS_FEATURE(inheritedQueries);
#define BEGIN_PHYS_EXT_CHECK(struct, stype) \
if(struct *ext = (struct *)FindNextStruct(&createInfo, stype)) \
{ \
struct avail = {stype}; \
VkPhysicalDeviceFeatures2 availBase = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2}; \
availBase.pNext = &avail; \
ObjDisp(physicalDevice)->GetPhysicalDeviceFeatures2(Unwrap(physicalDevice), &availBase); \
const char *structName = #struct;
#define END_PHYS_EXT_CHECK() }
#define CHECK_PHYS_EXT_FEATURE(feature) \
if(ext->feature && !avail.feature) \
{ \
SET_ERROR_RESULT(m_FailedReplayResult, ResultCode::APIHardwareUnsupported, \
"Capture requires physical device feature '" #feature \
"' in struct '%s' which is not supported\n\n%s", \
structName, GetPhysDeviceCompatString(false, false).c_str()); \
return false; \
}
VkPhysicalDeviceDescriptorIndexingFeatures descIndexingFeatures = {};
VkPhysicalDeviceVulkan12Features vulkan12Features = {};
VkPhysicalDeviceVulkan13Features vulkan13Features = {};
VkPhysicalDeviceSynchronization2Features sync2 = {};
if(ObjDisp(physicalDevice)->GetPhysicalDeviceFeatures2)
{
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceVulkan11Features,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(storageBuffer16BitAccess);
CHECK_PHYS_EXT_FEATURE(uniformAndStorageBuffer16BitAccess);
CHECK_PHYS_EXT_FEATURE(storagePushConstant16);
CHECK_PHYS_EXT_FEATURE(storageInputOutput16);
CHECK_PHYS_EXT_FEATURE(multiview);
CHECK_PHYS_EXT_FEATURE(multiviewGeometryShader);
CHECK_PHYS_EXT_FEATURE(multiviewTessellationShader);
CHECK_PHYS_EXT_FEATURE(variablePointersStorageBuffer);
CHECK_PHYS_EXT_FEATURE(variablePointers);
CHECK_PHYS_EXT_FEATURE(protectedMemory);
CHECK_PHYS_EXT_FEATURE(samplerYcbcrConversion);
CHECK_PHYS_EXT_FEATURE(shaderDrawParameters);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceVulkan12Features,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES);
{
vulkan12Features = *ext;
CHECK_PHYS_EXT_FEATURE(samplerMirrorClampToEdge);
CHECK_PHYS_EXT_FEATURE(drawIndirectCount);
CHECK_PHYS_EXT_FEATURE(storageBuffer8BitAccess);
CHECK_PHYS_EXT_FEATURE(uniformAndStorageBuffer8BitAccess);
CHECK_PHYS_EXT_FEATURE(storagePushConstant8);
CHECK_PHYS_EXT_FEATURE(shaderBufferInt64Atomics);
CHECK_PHYS_EXT_FEATURE(shaderSharedInt64Atomics);
CHECK_PHYS_EXT_FEATURE(shaderFloat16);
CHECK_PHYS_EXT_FEATURE(shaderInt8);
CHECK_PHYS_EXT_FEATURE(descriptorIndexing);
CHECK_PHYS_EXT_FEATURE(shaderInputAttachmentArrayDynamicIndexing);
CHECK_PHYS_EXT_FEATURE(shaderUniformTexelBufferArrayDynamicIndexing);
CHECK_PHYS_EXT_FEATURE(shaderStorageTexelBufferArrayDynamicIndexing);
CHECK_PHYS_EXT_FEATURE(shaderUniformBufferArrayNonUniformIndexing);
CHECK_PHYS_EXT_FEATURE(shaderSampledImageArrayNonUniformIndexing);
CHECK_PHYS_EXT_FEATURE(shaderStorageBufferArrayNonUniformIndexing);
CHECK_PHYS_EXT_FEATURE(shaderStorageImageArrayNonUniformIndexing);
CHECK_PHYS_EXT_FEATURE(shaderInputAttachmentArrayNonUniformIndexing);
CHECK_PHYS_EXT_FEATURE(shaderUniformTexelBufferArrayNonUniformIndexing);
CHECK_PHYS_EXT_FEATURE(shaderStorageTexelBufferArrayNonUniformIndexing);
CHECK_PHYS_EXT_FEATURE(descriptorBindingUniformBufferUpdateAfterBind);
CHECK_PHYS_EXT_FEATURE(descriptorBindingSampledImageUpdateAfterBind);
CHECK_PHYS_EXT_FEATURE(descriptorBindingStorageImageUpdateAfterBind);
CHECK_PHYS_EXT_FEATURE(descriptorBindingStorageBufferUpdateAfterBind);
CHECK_PHYS_EXT_FEATURE(descriptorBindingUniformTexelBufferUpdateAfterBind);
CHECK_PHYS_EXT_FEATURE(descriptorBindingStorageTexelBufferUpdateAfterBind);
CHECK_PHYS_EXT_FEATURE(descriptorBindingUpdateUnusedWhilePending);
CHECK_PHYS_EXT_FEATURE(descriptorBindingPartiallyBound);
CHECK_PHYS_EXT_FEATURE(descriptorBindingVariableDescriptorCount);
CHECK_PHYS_EXT_FEATURE(runtimeDescriptorArray);
CHECK_PHYS_EXT_FEATURE(samplerFilterMinmax);
CHECK_PHYS_EXT_FEATURE(scalarBlockLayout);
CHECK_PHYS_EXT_FEATURE(imagelessFramebuffer);
CHECK_PHYS_EXT_FEATURE(uniformBufferStandardLayout);
CHECK_PHYS_EXT_FEATURE(shaderSubgroupExtendedTypes);
CHECK_PHYS_EXT_FEATURE(separateDepthStencilLayouts);
CHECK_PHYS_EXT_FEATURE(hostQueryReset);
CHECK_PHYS_EXT_FEATURE(timelineSemaphore);
CHECK_PHYS_EXT_FEATURE(bufferDeviceAddress);
CHECK_PHYS_EXT_FEATURE(bufferDeviceAddressCaptureReplay);
CHECK_PHYS_EXT_FEATURE(bufferDeviceAddressMultiDevice);
CHECK_PHYS_EXT_FEATURE(vulkanMemoryModel);
CHECK_PHYS_EXT_FEATURE(vulkanMemoryModelDeviceScope);
CHECK_PHYS_EXT_FEATURE(vulkanMemoryModelAvailabilityVisibilityChains);
CHECK_PHYS_EXT_FEATURE(shaderOutputViewportIndex);
CHECK_PHYS_EXT_FEATURE(shaderOutputLayer);
CHECK_PHYS_EXT_FEATURE(subgroupBroadcastDynamicId);
m_SeparateDepthStencil |= (ext->separateDepthStencilLayouts != VK_FALSE);
if(ext->bufferDeviceAddress && !avail.bufferDeviceAddressCaptureReplay)
{
SET_ERROR_RESULT(
m_FailedReplayResult, ResultCode::APIHardwareUnsupported,
"Capture requires bufferDeviceAddress support, which is available, but "
"bufferDeviceAddressCaptureReplay support is not available which is required to "
"replay\n"
"\n%s",
GetPhysDeviceCompatString(false, false).c_str());
return false;
}
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceVulkan13Features,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES);
{
vulkan13Features = *ext;
CHECK_PHYS_EXT_FEATURE(robustImageAccess);
CHECK_PHYS_EXT_FEATURE(inlineUniformBlock);
CHECK_PHYS_EXT_FEATURE(descriptorBindingInlineUniformBlockUpdateAfterBind);
CHECK_PHYS_EXT_FEATURE(pipelineCreationCacheControl);
CHECK_PHYS_EXT_FEATURE(privateData);
CHECK_PHYS_EXT_FEATURE(shaderDemoteToHelperInvocation);
CHECK_PHYS_EXT_FEATURE(shaderTerminateInvocation);
CHECK_PHYS_EXT_FEATURE(subgroupSizeControl);
CHECK_PHYS_EXT_FEATURE(computeFullSubgroups);
CHECK_PHYS_EXT_FEATURE(synchronization2);
CHECK_PHYS_EXT_FEATURE(textureCompressionASTC_HDR);
CHECK_PHYS_EXT_FEATURE(shaderZeroInitializeWorkgroupMemory);
CHECK_PHYS_EXT_FEATURE(dynamicRendering);
CHECK_PHYS_EXT_FEATURE(shaderIntegerDotProduct);
CHECK_PHYS_EXT_FEATURE(maintenance4);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDevice8BitStorageFeatures,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(storageBuffer8BitAccess);
CHECK_PHYS_EXT_FEATURE(uniformAndStorageBuffer8BitAccess);
CHECK_PHYS_EXT_FEATURE(storagePushConstant8);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDevice16BitStorageFeatures,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(storageBuffer16BitAccess);
CHECK_PHYS_EXT_FEATURE(uniformAndStorageBuffer16BitAccess);
CHECK_PHYS_EXT_FEATURE(storagePushConstant16);
CHECK_PHYS_EXT_FEATURE(storageInputOutput16);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceASTCDecodeFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(decodeModeSharedExponent);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(
VkPhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(attachmentFeedbackLoopLayout);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(
VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR);
{
CHECK_PHYS_EXT_FEATURE(fragmentShaderBarycentric);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceMultiviewFeatures,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(multiview);
CHECK_PHYS_EXT_FEATURE(multiviewGeometryShader);
CHECK_PHYS_EXT_FEATURE(multiviewTessellationShader);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceFragmentDensityMapFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(fragmentDensityMap);
CHECK_PHYS_EXT_FEATURE(fragmentDensityMapDynamic);
CHECK_PHYS_EXT_FEATURE(fragmentDensityMapNonSubsampledImages);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceFragmentDensityMap2FeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(fragmentDensityMapDeferred);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(
VkPhysicalDeviceFragmentDensityMapOffsetFeaturesQCOM,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_FEATURES_QCOM);
{
CHECK_PHYS_EXT_FEATURE(fragmentDensityMapOffset);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceProtectedMemoryFeatures,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(protectedMemory);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceSamplerYcbcrConversionFeatures,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(samplerYcbcrConversion);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceShaderAtomicInt64Features,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(shaderBufferInt64Atomics);
CHECK_PHYS_EXT_FEATURE(shaderSharedInt64Atomics);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceShaderDrawParametersFeatures,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(shaderDrawParameters);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceShaderImageFootprintFeaturesNV,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_FOOTPRINT_FEATURES_NV);
{
CHECK_PHYS_EXT_FEATURE(imageFootprint);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceTransformFeedbackFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(transformFeedback);
CHECK_PHYS_EXT_FEATURE(geometryStreams);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceVariablePointerFeatures,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(variablePointersStorageBuffer);
CHECK_PHYS_EXT_FEATURE(variablePointers);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceVertexAttributeDivisorFeaturesKHR,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_KHR);
{
CHECK_PHYS_EXT_FEATURE(vertexAttributeInstanceRateDivisor);
CHECK_PHYS_EXT_FEATURE(vertexAttributeInstanceRateZeroDivisor);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceVulkanMemoryModelFeatures,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(vulkanMemoryModel);
CHECK_PHYS_EXT_FEATURE(vulkanMemoryModelDeviceScope);
CHECK_PHYS_EXT_FEATURE(vulkanMemoryModelAvailabilityVisibilityChains);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceConditionalRenderingFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(conditionalRendering);
CHECK_PHYS_EXT_FEATURE(inheritedConditionalRendering);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceHostQueryResetFeatures,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(hostQueryReset);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceDepthClipControlFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_CONTROL_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(depthClipControl);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(
VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVE_TOPOLOGY_LIST_RESTART_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(primitiveTopologyListRestart);
CHECK_PHYS_EXT_FEATURE(primitiveTopologyPatchListRestart);
m_ListRestart = ext->primitiveTopologyListRestart != VK_FALSE;
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVES_GENERATED_QUERY_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(primitivesGeneratedQuery);
CHECK_PHYS_EXT_FEATURE(primitivesGeneratedQueryWithRasterizerDiscard);
CHECK_PHYS_EXT_FEATURE(primitivesGeneratedQueryWithNonZeroStreams);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(
VkPhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(multisampledRenderToSingleSampled);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(
VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(rasterizationOrderColorAttachmentAccess);
CHECK_PHYS_EXT_FEATURE(rasterizationOrderDepthAttachmentAccess);
CHECK_PHYS_EXT_FEATURE(rasterizationOrderStencilAttachmentAccess);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceDepthClipEnableFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(depthClipEnable);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceYcbcrImageArraysFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_IMAGE_ARRAYS_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(ycbcrImageArrays);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceBufferDeviceAddressFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(bufferDeviceAddress);
CHECK_PHYS_EXT_FEATURE(bufferDeviceAddressCaptureReplay);
CHECK_PHYS_EXT_FEATURE(bufferDeviceAddressMultiDevice);
if(ext->bufferDeviceAddress && !avail.bufferDeviceAddressCaptureReplay)
{
SET_ERROR_RESULT(
m_FailedReplayResult, ResultCode::APIHardwareUnsupported,
"Capture requires bufferDeviceAddress support, which is available, but "
"bufferDeviceAddressCaptureReplay support is not available which is required to "
"replay\n"
"\n%s",
GetPhysDeviceCompatString(false, false).c_str());
return false;
}
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceBufferDeviceAddressFeatures,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(bufferDeviceAddress);
CHECK_PHYS_EXT_FEATURE(bufferDeviceAddressCaptureReplay);
CHECK_PHYS_EXT_FEATURE(bufferDeviceAddressMultiDevice);
if(ext->bufferDeviceAddress && !avail.bufferDeviceAddressCaptureReplay)
{
SET_ERROR_RESULT(
m_FailedReplayResult, ResultCode::APIHardwareUnsupported,
"Capture requires bufferDeviceAddress support, which is available, but "
"bufferDeviceAddressCaptureReplay support is not available which is required to "
"replay\n"
"\n%s",
GetPhysDeviceCompatString(false, false).c_str());
return false;
}
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceDescriptorIndexingFeatures,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES);
{
descIndexingFeatures = *ext;
CHECK_PHYS_EXT_FEATURE(shaderInputAttachmentArrayDynamicIndexing);
CHECK_PHYS_EXT_FEATURE(shaderUniformTexelBufferArrayDynamicIndexing);
CHECK_PHYS_EXT_FEATURE(shaderStorageTexelBufferArrayDynamicIndexing);
CHECK_PHYS_EXT_FEATURE(shaderUniformBufferArrayNonUniformIndexing);
CHECK_PHYS_EXT_FEATURE(shaderSampledImageArrayNonUniformIndexing);
CHECK_PHYS_EXT_FEATURE(shaderStorageBufferArrayNonUniformIndexing);
CHECK_PHYS_EXT_FEATURE(shaderStorageImageArrayNonUniformIndexing);
CHECK_PHYS_EXT_FEATURE(shaderInputAttachmentArrayNonUniformIndexing);
CHECK_PHYS_EXT_FEATURE(shaderUniformTexelBufferArrayNonUniformIndexing);
CHECK_PHYS_EXT_FEATURE(shaderStorageTexelBufferArrayNonUniformIndexing);
CHECK_PHYS_EXT_FEATURE(descriptorBindingUniformBufferUpdateAfterBind);
CHECK_PHYS_EXT_FEATURE(descriptorBindingSampledImageUpdateAfterBind);
CHECK_PHYS_EXT_FEATURE(descriptorBindingStorageImageUpdateAfterBind);
CHECK_PHYS_EXT_FEATURE(descriptorBindingStorageBufferUpdateAfterBind);
CHECK_PHYS_EXT_FEATURE(descriptorBindingUniformTexelBufferUpdateAfterBind);
CHECK_PHYS_EXT_FEATURE(descriptorBindingStorageTexelBufferUpdateAfterBind);
CHECK_PHYS_EXT_FEATURE(descriptorBindingUpdateUnusedWhilePending);
CHECK_PHYS_EXT_FEATURE(descriptorBindingPartiallyBound);
CHECK_PHYS_EXT_FEATURE(descriptorBindingVariableDescriptorCount);
CHECK_PHYS_EXT_FEATURE(runtimeDescriptorArray);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceUniformBufferStandardLayoutFeatures,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(uniformBufferStandardLayout);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(fragmentShaderSampleInterlock);
CHECK_PHYS_EXT_FEATURE(fragmentShaderPixelInterlock);
CHECK_PHYS_EXT_FEATURE(fragmentShaderShadingRateInterlock);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(
VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(shaderDemoteToHelperInvocation);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(texelBufferAlignment);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceIndexTypeUint8FeaturesKHR,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_KHR);
{
CHECK_PHYS_EXT_FEATURE(indexTypeUint8);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceImagelessFramebufferFeatures,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(imagelessFramebuffer);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceSubgroupSizeControlFeatures,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(subgroupSizeControl);
CHECK_PHYS_EXT_FEATURE(computeFullSubgroups);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(
VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR);
{
CHECK_PHYS_EXT_FEATURE(pipelineExecutableInfo);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceLineRasterizationFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(rectangularLines);
CHECK_PHYS_EXT_FEATURE(bresenhamLines);
CHECK_PHYS_EXT_FEATURE(smoothLines);
CHECK_PHYS_EXT_FEATURE(stippledRectangularLines);
CHECK_PHYS_EXT_FEATURE(stippledBresenhamLines);
CHECK_PHYS_EXT_FEATURE(stippledSmoothLines);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(shaderSubgroupExtendedTypes);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceCoherentMemoryFeaturesAMD,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COHERENT_MEMORY_FEATURES_AMD);
{
CHECK_PHYS_EXT_FEATURE(deviceCoherentMemory);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceShaderClockFeaturesKHR,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CLOCK_FEATURES_KHR);
{
CHECK_PHYS_EXT_FEATURE(shaderSubgroupClock);
CHECK_PHYS_EXT_FEATURE(shaderDeviceClock);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceMemoryPriorityFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(memoryPriority);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceScalarBlockLayoutFeatures,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(scalarBlockLayout);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceShaderFloat16Int8Features,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(shaderFloat16);
CHECK_PHYS_EXT_FEATURE(shaderInt8);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceTimelineSemaphoreFeatures,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(timelineSemaphore);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(separateDepthStencilLayouts);
m_SeparateDepthStencil |= (ext->separateDepthStencilLayouts != VK_FALSE);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDevicePerformanceQueryFeaturesKHR,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR);
{
CHECK_PHYS_EXT_FEATURE(performanceCounterQueryPools);
CHECK_PHYS_EXT_FEATURE(performanceCounterMultipleQueryPools);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceInlineUniformBlockFeatures,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(inlineUniformBlock);
CHECK_PHYS_EXT_FEATURE(descriptorBindingInlineUniformBlockUpdateAfterBind);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceCustomBorderColorFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(customBorderColors);
CHECK_PHYS_EXT_FEATURE(customBorderColorWithoutFormat);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceRobustness2FeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(robustBufferAccess2);
CHECK_PHYS_EXT_FEATURE(robustImageAccess2);
CHECK_PHYS_EXT_FEATURE(nullDescriptor);
m_NULLDescriptorsAllowed |= (ext->nullDescriptor != VK_FALSE);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(
VkPhysicalDevicePipelineCreationCacheControlFeatures,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(pipelineCreationCacheControl);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceComputeShaderDerivativesFeaturesNV,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV);
{
CHECK_PHYS_EXT_FEATURE(computeDerivativeGroupQuads);
CHECK_PHYS_EXT_FEATURE(computeDerivativeGroupLinear);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceExtendedDynamicStateFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(extendedDynamicState);
m_ExtendedDynState = (ext->extendedDynamicState != VK_FALSE);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceShaderTerminateInvocationFeatures,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(shaderTerminateInvocation);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceImageRobustnessFeatures,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(robustImageAccess);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceShaderAtomicFloatFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(shaderBufferFloat32Atomics);
CHECK_PHYS_EXT_FEATURE(shaderBufferFloat32AtomicAdd);
CHECK_PHYS_EXT_FEATURE(shaderBufferFloat64Atomics);
CHECK_PHYS_EXT_FEATURE(shaderBufferFloat64AtomicAdd);
CHECK_PHYS_EXT_FEATURE(shaderSharedFloat32Atomics);
CHECK_PHYS_EXT_FEATURE(shaderSharedFloat32AtomicAdd);
CHECK_PHYS_EXT_FEATURE(shaderSharedFloat64Atomics);
CHECK_PHYS_EXT_FEATURE(shaderSharedFloat64AtomicAdd);
CHECK_PHYS_EXT_FEATURE(shaderImageFloat32Atomics);
CHECK_PHYS_EXT_FEATURE(shaderImageFloat32AtomicAdd);
CHECK_PHYS_EXT_FEATURE(sparseImageFloat32Atomics);
CHECK_PHYS_EXT_FEATURE(sparseImageFloat32AtomicAdd);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_ATOMIC_INT64_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(shaderImageInt64Atomics);
CHECK_PHYS_EXT_FEATURE(sparseImageInt64Atomics);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(
VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeatures,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(shaderZeroInitializeWorkgroupMemory);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(
VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_FEATURES_KHR);
{
CHECK_PHYS_EXT_FEATURE(workgroupMemoryExplicitLayout);
CHECK_PHYS_EXT_FEATURE(workgroupMemoryExplicitLayoutScalarBlockLayout);
CHECK_PHYS_EXT_FEATURE(workgroupMemoryExplicitLayout8BitAccess);
CHECK_PHYS_EXT_FEATURE(workgroupMemoryExplicitLayout16BitAccess);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceSynchronization2Features,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES);
{
sync2 = *ext;
CHECK_PHYS_EXT_FEATURE(synchronization2);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceMaintenance4Features,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(maintenance4);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceShaderIntegerDotProductFeatures,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(shaderIntegerDotProduct);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(
VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_FEATURES_KHR);
{
CHECK_PHYS_EXT_FEATURE(shaderSubgroupUniformControlFlow);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(shaderBufferFloat16Atomics);
CHECK_PHYS_EXT_FEATURE(shaderBufferFloat16AtomicAdd);
CHECK_PHYS_EXT_FEATURE(shaderBufferFloat16AtomicMinMax);
CHECK_PHYS_EXT_FEATURE(shaderBufferFloat32AtomicMinMax);
CHECK_PHYS_EXT_FEATURE(shaderBufferFloat64AtomicMinMax);
CHECK_PHYS_EXT_FEATURE(shaderSharedFloat16Atomics);
CHECK_PHYS_EXT_FEATURE(shaderSharedFloat16AtomicAdd);
CHECK_PHYS_EXT_FEATURE(shaderSharedFloat16AtomicMinMax);
CHECK_PHYS_EXT_FEATURE(shaderSharedFloat32AtomicMinMax);
CHECK_PHYS_EXT_FEATURE(shaderSharedFloat64AtomicMinMax);
CHECK_PHYS_EXT_FEATURE(shaderImageFloat32AtomicMinMax);
CHECK_PHYS_EXT_FEATURE(sparseImageFloat32AtomicMinMax);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceYcbcr2Plane444FormatsFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_2_PLANE_444_FORMATS_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(ycbcr2plane444Formats);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RGBA10X6_FORMATS_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(formatRgba10x6WithoutYCbCrSampler);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceGlobalPriorityQueryFeaturesKHR,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_KHR);
{
CHECK_PHYS_EXT_FEATURE(globalPriorityQuery);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceColorWriteEnableFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(colorWriteEnable);
m_DynColorWrite = (ext->colorWriteEnable != VK_FALSE);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceExtendedDynamicState2FeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(extendedDynamicState2);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState2LogicOp);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState2PatchControlPoints);
m_ExtendedDynState2 = (ext->extendedDynamicState2 != VK_FALSE);
m_ExtendedDynState2Logic = (ext->extendedDynamicState2LogicOp != VK_FALSE);
m_ExtendedDynState2CPs = (ext->extendedDynamicState2PatchControlPoints != VK_FALSE);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(vertexInputDynamicState);
m_DynVertexInput = (ext->vertexInputDynamicState != VK_FALSE);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(graphicsPipelineLibrary);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceDynamicRenderingFeatures,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(dynamicRendering);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDevice4444FormatsFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(formatA4R4G4B4);
CHECK_PHYS_EXT_FEATURE(formatA4B4G4R4);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceTextureCompressionASTCHDRFeatures,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES);
{
CHECK_PHYS_EXT_FEATURE(textureCompressionASTC_HDR);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceFragmentShadingRateFeaturesKHR,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR);
{
CHECK_PHYS_EXT_FEATURE(pipelineFragmentShadingRate);
CHECK_PHYS_EXT_FEATURE(primitiveFragmentShadingRate);
CHECK_PHYS_EXT_FEATURE(attachmentFragmentShadingRate);
m_FragmentShadingRate = (ext->pipelineFragmentShadingRate != VK_FALSE) ||
(ext->primitiveFragmentShadingRate != VK_FALSE) ||
(ext->attachmentFragmentShadingRate != VK_FALSE);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(mutableDescriptorType);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(
VkPhysicalDevicePageableDeviceLocalMemoryFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PAGEABLE_DEVICE_LOCAL_MEMORY_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(pageableDeviceLocalMemory);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(swapchainMaintenance1);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceBorderColorSwizzleFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BORDER_COLOR_SWIZZLE_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(borderColorSwizzle);
CHECK_PHYS_EXT_FEATURE(borderColorSwizzleFromImage);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceNonSeamlessCubeMapFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NON_SEAMLESS_CUBE_MAP_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(nonSeamlessCubeMap);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceDepthClampZeroOneFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLAMP_ZERO_ONE_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(depthClampZeroOne);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceImageViewMinLodFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(minLod);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceProvokingVertexFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(provokingVertexLast);
CHECK_PHYS_EXT_FEATURE(transformFeedbackPreservesProvokingVertex);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(
VkPhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(attachmentFeedbackLoopDynamicState);
m_DynAttachmentLoop = ext->attachmentFeedbackLoopDynamicState != VK_FALSE;
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceImage2DViewOf3DFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(image2DViewOf3D);
CHECK_PHYS_EXT_FEATURE(sampler2DViewOf3D);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceExtendedDynamicState3FeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3TessellationDomainOrigin);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3DepthClampEnable);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3PolygonMode);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3RasterizationSamples);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3SampleMask);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3AlphaToCoverageEnable);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3AlphaToOneEnable);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3LogicOpEnable);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3ColorBlendEnable);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3ColorBlendEquation);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3ColorWriteMask);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3RasterizationStream);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3ConservativeRasterizationMode);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3ExtraPrimitiveOverestimationSize);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3DepthClipEnable);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3SampleLocationsEnable);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3ColorBlendAdvanced);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3ProvokingVertexMode);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3LineRasterizationMode);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3LineStippleEnable);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3DepthClipNegativeOneToOne);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3ViewportWScalingEnable);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3ViewportSwizzle);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3CoverageToColorEnable);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3CoverageToColorLocation);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3CoverageModulationMode);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3CoverageModulationTableEnable);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3CoverageModulationTable);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3CoverageReductionMode);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3RepresentativeFragmentTestEnable);
CHECK_PHYS_EXT_FEATURE(extendedDynamicState3ShadingRateImageEnable);
m_ExtendedDynState3TesselDomain =
(ext->extendedDynamicState3TessellationDomainOrigin != VK_FALSE);
m_ExtendedDynState3DepthClampEnable =
(ext->extendedDynamicState3DepthClampEnable != VK_FALSE);
m_ExtendedDynState3PolyMode = (ext->extendedDynamicState3PolygonMode != VK_FALSE);
m_ExtendedDynState3RastSamples = (ext->extendedDynamicState3RasterizationSamples != VK_FALSE);
m_ExtendedDynState3SampleMask = (ext->extendedDynamicState3SampleMask != VK_FALSE);
m_ExtendedDynState3AlphaToCover =
(ext->extendedDynamicState3AlphaToCoverageEnable != VK_FALSE);
m_ExtendedDynState3AlphaToOne = (ext->extendedDynamicState3AlphaToOneEnable != VK_FALSE);
m_ExtendedDynState3LogicEnable = (ext->extendedDynamicState3LogicOpEnable != VK_FALSE);
m_ExtendedDynState3CBEnable = (ext->extendedDynamicState3ColorBlendEnable != VK_FALSE);
m_ExtendedDynState3CBEquation = (ext->extendedDynamicState3ColorBlendEquation != VK_FALSE);
m_ExtendedDynState3WriteMask = (ext->extendedDynamicState3ColorWriteMask != VK_FALSE);
m_ExtendedDynState3RastStream = (ext->extendedDynamicState3RasterizationStream != VK_FALSE);
m_ExtendedDynState3ConservRast =
(ext->extendedDynamicState3ConservativeRasterizationMode != VK_FALSE);
m_ExtendedDynState3PrimOverest =
(ext->extendedDynamicState3ExtraPrimitiveOverestimationSize != VK_FALSE);
m_ExtendedDynState3DepthClip = (ext->extendedDynamicState3DepthClipEnable != VK_FALSE);
m_ExtendedDynState3SampleLoc = (ext->extendedDynamicState3SampleLocationsEnable != VK_FALSE);
m_ExtendedDynState3ProvokingVert =
(ext->extendedDynamicState3ProvokingVertexMode != VK_FALSE);
m_ExtendedDynState3LineRast = (ext->extendedDynamicState3LineRasterizationMode != VK_FALSE);
m_ExtendedDynState3LineStipple = (ext->extendedDynamicState3LineStippleEnable != VK_FALSE);
m_ExtendedDynState3DepthClipNeg =
(ext->extendedDynamicState3DepthClipNegativeOneToOne != VK_FALSE);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceMeshShaderFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(taskShader);
CHECK_PHYS_EXT_FEATURE(meshShader);
CHECK_PHYS_EXT_FEATURE(multiviewMeshShader);
CHECK_PHYS_EXT_FEATURE(primitiveFragmentShadingRateMeshShader);
CHECK_PHYS_EXT_FEATURE(meshShaderQueries);
m_MeshShaders = ext->meshShader != VK_FALSE;
m_TaskShaders = ext->taskShader != VK_FALSE;
m_MeshQueries = avail.meshShaderQueries != VK_FALSE;
if(avail.meshShaderQueries)
ext->meshShaderQueries = true;
else
RDCWARN("meshShaderQueries = false, mesh shader performance counters unavailable");
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceAccelerationStructureFeaturesKHR,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR);
{
CHECK_PHYS_EXT_FEATURE(accelerationStructure)
CHECK_PHYS_EXT_FEATURE(accelerationStructureCaptureReplay)
CHECK_PHYS_EXT_FEATURE(accelerationStructureIndirectBuild)
CHECK_PHYS_EXT_FEATURE(descriptorBindingAccelerationStructureUpdateAfterBind)
if(ext->accelerationStructure && !avail.accelerationStructureCaptureReplay)
{
SET_ERROR_RESULT(
m_FailedReplayResult, ResultCode::APIHardwareUnsupported,
"Capture requires accelerationStructure support, which is available, but "
"accelerationStructureCaptureReplay support is not available which is required to "
"replay\n"
"\n%s",
GetPhysDeviceCompatString(false, false).c_str());
return false;
}
m_AccelerationStructures = ext->accelerationStructure != VK_FALSE;
if(m_AccelerationStructures)
{
RDCLOG(
"Ray tracing acceleration structures requested, allocating all device memory with "
"VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT");
ext->accelerationStructureCaptureReplay = VK_TRUE;
}
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceNestedCommandBufferFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NESTED_COMMAND_BUFFER_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(nestedCommandBuffer);
CHECK_PHYS_EXT_FEATURE(nestedCommandBufferRendering);
CHECK_PHYS_EXT_FEATURE(nestedCommandBufferSimultaneousUse);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceShaderObjectFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(shaderObject);
m_ShaderObject = ext->shaderObject != VK_FALSE;
}
END_PHYS_EXT_CHECK();
}
if(availFeatures.depthClamp)
enabledFeatures.depthClamp = true;
else
RDCWARN(
"depthClamp = false, overlays like highlight drawcall won't show depth-clipped pixels.");
// we have a fallback for this case, so no warning
if(availFeatures.fillModeNonSolid)
enabledFeatures.fillModeNonSolid = true;
// don't warn if this isn't available, we just won't report the counters
if(availFeatures.pipelineStatisticsQuery)
enabledFeatures.pipelineStatisticsQuery = true;
if(availFeatures.geometryShader)
enabledFeatures.geometryShader = true;
else
RDCWARN(
"geometryShader = false, pixel history primitive ID and triangle size overlay will not "
"be available, and local rendering on this device will not support lit mesh views.");
// enable these features for simplicity, since we use them when available in the shader
// debugging to simplify samples. If minlod isn't used then we omit it, and that's fine because
// the application's shaders wouldn't have been using minlod. We use gatherExtended for gather
// offsets, which means if it's not supported then we can't debug constant offsets properly
// (because we pass offsets as uniforms), but that's not a big deal.
if(availFeatures.shaderImageGatherExtended)
enabledFeatures.shaderImageGatherExtended = true;
if(availFeatures.shaderResourceMinLod)
enabledFeatures.shaderResourceMinLod = true;
if(availFeatures.imageCubeArray)
enabledFeatures.imageCubeArray = true;
bool descIndexingAllowsRBA = true;
if(vulkan12Features.descriptorBindingUniformBufferUpdateAfterBind ||
vulkan12Features.descriptorBindingStorageBufferUpdateAfterBind ||
vulkan12Features.descriptorBindingUniformTexelBufferUpdateAfterBind ||
vulkan12Features.descriptorBindingStorageTexelBufferUpdateAfterBind)
{
// if any update after bind feature is enabled, check robustBufferAccessUpdateAfterBind
VkPhysicalDeviceVulkan12Properties vulkan12Props = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES,
};
VkPhysicalDeviceProperties2 availBase = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2};
availBase.pNext = &vulkan12Props;
ObjDisp(physicalDevice)->GetPhysicalDeviceProperties2(Unwrap(physicalDevice), &availBase);
descIndexingAllowsRBA = vulkan12Props.robustBufferAccessUpdateAfterBind != VK_FALSE;
}
if(descIndexingFeatures.descriptorBindingUniformBufferUpdateAfterBind ||
descIndexingFeatures.descriptorBindingStorageBufferUpdateAfterBind ||
descIndexingFeatures.descriptorBindingUniformTexelBufferUpdateAfterBind ||
descIndexingFeatures.descriptorBindingStorageTexelBufferUpdateAfterBind)
{
// if any update after bind feature is enabled, check robustBufferAccessUpdateAfterBind
VkPhysicalDeviceDescriptorIndexingProperties descIndexingProps = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES,
};
VkPhysicalDeviceProperties2 availBase = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2};
availBase.pNext = &descIndexingProps;
ObjDisp(physicalDevice)->GetPhysicalDeviceProperties2(Unwrap(physicalDevice), &availBase);
descIndexingAllowsRBA = descIndexingProps.robustBufferAccessUpdateAfterBind != VK_FALSE;
}
if(availFeatures.robustBufferAccess && !descIndexingAllowsRBA)
{
// if the feature is available but we can't use it, warn
RDCWARN(
"robustBufferAccess is available, but cannot be enabled due to "
"robustBufferAccessUpdateAfterBind not being avilable and some UpdateAfterBind features "
"being enabled. "
"out of bounds access due to bugs in application or RenderDoc may cause crashes");
}
else
{
// either the feature is available, and we enable it, or it's not available at all.
if(availFeatures.robustBufferAccess)
enabledFeatures.robustBufferAccess = true;
else
RDCWARN(
"robustBufferAccess = false, out of bounds access due to bugs in application or "
"RenderDoc may cause crashes");
}
if(availFeatures.shaderInt64)
enabledFeatures.shaderInt64 = true;
else
RDCWARN("shaderInt64 = false, feedback from shaders will use less reliable fallback.");
if(availFeatures.shaderStorageImageWriteWithoutFormat)
enabledFeatures.shaderStorageImageWriteWithoutFormat = true;
else
RDCWARN(
"shaderStorageImageWriteWithoutFormat = false, save/load from 2DMS textures will not be "
"possible");
if(availFeatures.shaderStorageImageMultisample)
enabledFeatures.shaderStorageImageMultisample = true;
else
RDCWARN(
"shaderStorageImageMultisample = false, accurately replaying 2DMS textures will not be "
"possible");
if(availFeatures.occlusionQueryPrecise)
enabledFeatures.occlusionQueryPrecise = true;
else
RDCWARN("occlusionQueryPrecise = false, samples passed counter will not be available");
if(availFeatures.fragmentStoresAndAtomics)
enabledFeatures.fragmentStoresAndAtomics = true;
else
RDCWARN(
"fragmentStoresAndAtomics = false, quad overdraw overlay will not be available and "
"feedback from shaders will not be fetched for fragment stage");
if(availFeatures.vertexPipelineStoresAndAtomics)
enabledFeatures.vertexPipelineStoresAndAtomics = true;
else
RDCWARN(
"vertexPipelineStoresAndAtomics = false, feedback from shaders will not be fetched for "
"vertex stages");
if(availFeatures.sampleRateShading)
enabledFeatures.sampleRateShading = true;
else
RDCWARN(
"sampleRateShading = false, save/load from depth 2DMS textures will not be "
"possible");
// patch the enabled features
if(enabledFeatures2)
enabledFeatures2->features = enabledFeatures;
else
createInfo.pEnabledFeatures = &enabledFeatures;
uint32_t numExts = 0;
VkResult vkr =
ObjDisp(physicalDevice)
->EnumerateDeviceExtensionProperties(Unwrap(physicalDevice), NULL, &numExts, NULL);
CheckVkResult(vkr);
VkExtensionProperties *exts = new VkExtensionProperties[numExts];
vkr = ObjDisp(physicalDevice)
->EnumerateDeviceExtensionProperties(Unwrap(physicalDevice), NULL, &numExts, exts);
CheckVkResult(vkr);
for(uint32_t i = 0; i < numExts; i++)
RDCLOG("Dev Ext %u: %s (%u)", i, exts[i].extensionName, exts[i].specVersion);
SAFE_DELETE_ARRAY(exts);
VkPhysicalDeviceProperties physProps;
ObjDisp(physicalDevice)->GetPhysicalDeviceProperties(Unwrap(physicalDevice), &physProps);
VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR pipeExecFeatures = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR,
};
if(pipeExec)
{
VkPhysicalDeviceFeatures2 availBase = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
availBase.pNext = &pipeExecFeatures;
ObjDisp(physicalDevice)->GetPhysicalDeviceFeatures2(Unwrap(physicalDevice), &availBase);
if(pipeExecFeatures.pipelineExecutableInfo)
{
// see if there's an existing struct
VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR *existing =
(VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR *)FindNextStruct(
&createInfo,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR);
if(existing)
{
// if so, make sure the feature is enabled
existing->pipelineExecutableInfo = VK_TRUE;
}
else
{
// otherwise, add our own, and push it onto the pNext array
pipeExecFeatures.pipelineExecutableInfo = VK_TRUE;
pipeExecFeatures.pNext = (void *)createInfo.pNext;
createInfo.pNext = &pipeExecFeatures;
}
}
else
{
RDCWARN(
"VK_KHR_pipeline_executable_properties is available, but the physical device feature "
"is not. Disabling");
Extensions.removeOne(VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME);
}
}
VkPhysicalDeviceTransformFeedbackFeaturesEXT xfbFeatures = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT,
};
// if we're enabling XFB, make sure we can enable the physical device feature
if(xfb)
{
VkPhysicalDeviceFeatures2 availBase = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
availBase.pNext = &xfbFeatures;
ObjDisp(physicalDevice)->GetPhysicalDeviceFeatures2(Unwrap(physicalDevice), &availBase);
if(xfbFeatures.transformFeedback)
{
// see if there's an existing struct
VkPhysicalDeviceTransformFeedbackFeaturesEXT *existing =
(VkPhysicalDeviceTransformFeedbackFeaturesEXT *)FindNextStruct(
&createInfo, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT);
if(existing)
{
// if so, make sure the feature is enabled
existing->transformFeedback = VK_TRUE;
}
else
{
// otherwise, add our own, and push it onto the pNext array
xfbFeatures.transformFeedback = VK_TRUE;
xfbFeatures.geometryStreams = VK_FALSE;
xfbFeatures.pNext = (void *)createInfo.pNext;
createInfo.pNext = &xfbFeatures;
}
}
else
{
RDCWARN(
"VK_EXT_transform_feedback is available, but the physical device feature is not. "
"Disabling");
Extensions.removeOne(VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME);
}
}
VkPhysicalDevicePerformanceQueryFeaturesKHR perfFeatures = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR,
};
if(perfQuery)
{
VkPhysicalDeviceFeatures2 availBase = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
m_PhysicalDeviceData.performanceQueryFeatures.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR;
availBase.pNext = &perfFeatures;
ObjDisp(physicalDevice)->GetPhysicalDeviceFeatures2(Unwrap(physicalDevice), &availBase);
m_PhysicalDeviceData.performanceQueryFeatures = perfFeatures;
if(perfFeatures.performanceCounterQueryPools)
{
VkPhysicalDevicePerformanceQueryFeaturesKHR *existing =
(VkPhysicalDevicePerformanceQueryFeaturesKHR *)FindNextStruct(
&createInfo, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR);
if(existing)
{
existing->performanceCounterQueryPools = VK_TRUE;
}
else
{
perfFeatures.performanceCounterQueryPools = VK_TRUE;
perfFeatures.performanceCounterMultipleQueryPools = VK_FALSE;
perfFeatures.pNext = (void *)createInfo.pNext;
createInfo.pNext = &perfFeatures;
}
}
else
{
Extensions.removeOne(VK_KHR_PERFORMANCE_QUERY_EXTENSION_NAME);
}
}
VkPhysicalDeviceScalarBlockLayoutFeaturesEXT scalarBlockEXTFeatures = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT,
};
if(RDCMIN(m_EnabledExtensions.vulkanVersion, physProps.apiVersion) >= VK_MAKE_VERSION(1, 2, 0))
{
VkPhysicalDeviceVulkan12Features avail12Features = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
};
VkPhysicalDeviceFeatures2 availBase = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
availBase.pNext = &avail12Features;
ObjDisp(physicalDevice)->GetPhysicalDeviceFeatures2(Unwrap(physicalDevice), &availBase);
if(avail12Features.scalarBlockLayout)
{
VkPhysicalDeviceVulkan12Features *existing =
(VkPhysicalDeviceVulkan12Features *)FindNextStruct(
&createInfo, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES);
if(existing)
{
existing->scalarBlockLayout = VK_TRUE;
}
else
{
VkPhysicalDeviceScalarBlockLayoutFeaturesEXT *existingEXT =
(VkPhysicalDeviceScalarBlockLayoutFeaturesEXT *)FindNextStruct(
&createInfo, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT);
if(existingEXT)
{
existingEXT->scalarBlockLayout = VK_TRUE;
}
else
{
// don't add a new VkPhysicalDeviceVulkan12Features to the pNext chain because if we do
// we have to remove any components etc. Instead just add the individual
// VkPhysicalDeviceScalarBlockLayoutFeaturesEXT
scalarBlockEXTFeatures.scalarBlockLayout = VK_TRUE;
scalarBlockEXTFeatures.pNext = (void *)createInfo.pNext;
createInfo.pNext = &scalarBlockEXTFeatures;
}
}
}
}
else if(scalarBlock)
{
VkPhysicalDeviceScalarBlockLayoutFeaturesEXT scalarAvail = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT,
};
VkPhysicalDeviceFeatures2 availBase = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
availBase.pNext = &scalarAvail;
ObjDisp(physicalDevice)->GetPhysicalDeviceFeatures2(Unwrap(physicalDevice), &availBase);
if(scalarAvail.scalarBlockLayout)
{
// see if there's an existing struct
VkPhysicalDeviceScalarBlockLayoutFeaturesEXT *existing =
(VkPhysicalDeviceScalarBlockLayoutFeaturesEXT *)FindNextStruct(
&createInfo, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT);
if(existing)
{
existing->scalarBlockLayout = VK_TRUE;
}
else
{
// otherwise, add our own, and push it onto the pNext array
scalarBlockEXTFeatures.scalarBlockLayout = VK_TRUE;
scalarBlockEXTFeatures.pNext = (void *)createInfo.pNext;
createInfo.pNext = &scalarBlockEXTFeatures;
}
}
else
{
RDCWARN(
"VK_EXT_scalar_block_layout is available, but the physical device feature "
"is not. Disabling");
Extensions.removeOne(VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME);
}
}
VkPhysicalDeviceBufferDeviceAddressFeaturesEXT bufAddrEXTFeatures = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT,
};
VkPhysicalDeviceBufferDeviceAddressFeaturesKHR bufAddrKHRFeatures = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR,
};
if(RDCMIN(m_EnabledExtensions.vulkanVersion, physProps.apiVersion) >= VK_MAKE_VERSION(1, 3, 0))
{
// VK_EXT_extended_dynamic_state and VK_EXT_extended_dynamic_state2 were unconditionally
// promoted and considered implicitly enabled in vulkan 1.3
m_ExtendedDynState = true;
m_ExtendedDynState2 = true;
// logic and patch CPs were not
}
if(RDCMIN(m_EnabledExtensions.vulkanVersion, physProps.apiVersion) >= VK_MAKE_VERSION(1, 2, 0))
{
VkPhysicalDeviceVulkan12Features avail12Features = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
};
VkPhysicalDeviceFeatures2 availBase = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
availBase.pNext = &avail12Features;
ObjDisp(physicalDevice)->GetPhysicalDeviceFeatures2(Unwrap(physicalDevice), &availBase);
if(avail12Features.bufferDeviceAddress)
{
VkPhysicalDeviceVulkan12Features *existing =
(VkPhysicalDeviceVulkan12Features *)FindNextStruct(
&createInfo, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES);
if(existing)
{
if(existing->bufferDeviceAddress)
existing->bufferDeviceAddressCaptureReplay = VK_TRUE;
existing->bufferDeviceAddress = VK_TRUE;
}
else
{
VkPhysicalDeviceBufferDeviceAddressFeaturesKHR *existingKHR =
(VkPhysicalDeviceBufferDeviceAddressFeaturesKHR *)FindNextStruct(
&createInfo, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR);
VkPhysicalDeviceBufferDeviceAddressFeaturesEXT *existingEXT =
(VkPhysicalDeviceBufferDeviceAddressFeaturesEXT *)FindNextStruct(
&createInfo, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT);
if(existingKHR)
{
if(existingKHR->bufferDeviceAddress)
existingKHR->bufferDeviceAddressCaptureReplay = VK_TRUE;
existingKHR->bufferDeviceAddress = VK_TRUE;
}
else if(existingEXT)
{
if(existingEXT->bufferDeviceAddress)
existingEXT->bufferDeviceAddressCaptureReplay = VK_TRUE;
existingEXT->bufferDeviceAddress = VK_TRUE;
}
else
{
// don't add a new VkPhysicalDeviceVulkan12Features to the pNext chain because if we do
// we have to remove any components etc. Instead just add the individual
// VkPhysicalDeviceBufferDeviceAddressFeaturesKHR
bufAddrKHRFeatures.bufferDeviceAddress = VK_TRUE;
bufAddrKHRFeatures.bufferDeviceAddressMultiDevice = VK_FALSE;
bufAddrKHRFeatures.pNext = (void *)createInfo.pNext;
createInfo.pNext = &bufAddrKHRFeatures;
}
}
}
}
else if(KHRbuffer)
{
VkPhysicalDeviceFeatures2 availBase = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
availBase.pNext = &bufAddrKHRFeatures;
ObjDisp(physicalDevice)->GetPhysicalDeviceFeatures2(Unwrap(physicalDevice), &availBase);
if(bufAddrKHRFeatures.bufferDeviceAddress)
{
// see if there's an existing struct
VkPhysicalDeviceBufferDeviceAddressFeaturesKHR *existing =
(VkPhysicalDeviceBufferDeviceAddressFeaturesKHR *)FindNextStruct(
&createInfo, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR);
if(existing)
{
if(existing->bufferDeviceAddress)
existing->bufferDeviceAddressCaptureReplay = VK_TRUE;
// if so, make sure the feature is enabled
existing->bufferDeviceAddress = VK_TRUE;
}
else
{
// otherwise, add our own, and push it onto the pNext array
bufAddrKHRFeatures.bufferDeviceAddress = VK_TRUE;
bufAddrKHRFeatures.bufferDeviceAddressMultiDevice = VK_FALSE;
bufAddrKHRFeatures.pNext = (void *)createInfo.pNext;
createInfo.pNext = &bufAddrKHRFeatures;
}
}
else
{
RDCWARN(
"VK_KHR_buffer_device_address is available, but the physical device feature "
"is not. Disabling");
Extensions.removeOne(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
}
}
else if(EXTbuffer)
{
VkPhysicalDeviceFeatures2 availBase = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
availBase.pNext = &bufAddrEXTFeatures;
ObjDisp(physicalDevice)->GetPhysicalDeviceFeatures2(Unwrap(physicalDevice), &availBase);
if(bufAddrEXTFeatures.bufferDeviceAddress)
{
// see if there's an existing struct
VkPhysicalDeviceBufferDeviceAddressFeaturesEXT *existing =
(VkPhysicalDeviceBufferDeviceAddressFeaturesEXT *)FindNextStruct(
&createInfo, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT);
if(existing)
{
if(existing->bufferDeviceAddress)
existing->bufferDeviceAddressCaptureReplay = VK_TRUE;
// if so, make sure the feature is enabled
existing->bufferDeviceAddress = VK_TRUE;
}
else
{
// otherwise, add our own, and push it onto the pNext array
bufAddrEXTFeatures.bufferDeviceAddress = VK_TRUE;
bufAddrEXTFeatures.bufferDeviceAddressMultiDevice = VK_FALSE;
bufAddrEXTFeatures.pNext = (void *)createInfo.pNext;
createInfo.pNext = &bufAddrEXTFeatures;
}
}
else
{
RDCWARN(
"VK_EXT_buffer_device_address is available, but the physical device feature "
"is not. Disabling");
Extensions.removeOne(VK_EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
}
}
rdcarray<const char *> layerArray;
layerArray.resize(m_InitParams.Layers.size());
for(size_t i = 0; i < m_InitParams.Layers.size(); i++)
layerArray[i] = m_InitParams.Layers[i].c_str();
createInfo.enabledLayerCount = 0;
createInfo.ppEnabledLayerNames = NULL;
rdcarray<const char *> extArray;
extArray.resize(Extensions.size());
for(size_t i = 0; i < Extensions.size(); i++)
extArray[i] = Extensions[i].c_str();
createInfo.enabledExtensionCount = (uint32_t)extArray.size();
createInfo.ppEnabledExtensionNames = extArray.data();
byte *tempMem = GetTempMemory(GetNextPatchSize(createInfo.pNext));
UnwrapNextChain(m_State, "VkDeviceCreateInfo", tempMem, (VkBaseInStructure *)&createInfo);
VkDeviceGroupDeviceCreateInfo *device_group_info =
(VkDeviceGroupDeviceCreateInfo *)FindNextStruct(
&createInfo, VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO);
// decode physical devices that are actually indices
if(device_group_info)
{
VkPhysicalDevice *physDevs = (VkPhysicalDevice *)device_group_info->pPhysicalDevices;
for(uint32_t i = 0; i < device_group_info->physicalDeviceCount; i++)
physDevs[i] = Unwrap(m_PhysicalDevices[GetPhysicalDeviceIndexFromHandle(physDevs[i])]);
}
vkr = GetDeviceDispatchTable(NULL)->CreateDevice(Unwrap(physicalDevice), &createInfo, NULL,
&device);
if(vkr != VK_SUCCESS && !queuePriorities.empty())
{
RDCWARN("Failed to create logical device: %s. Reducing queue priorities", ToStr(vkr).c_str());
for(VkDeviceQueueGlobalPriorityCreateInfoKHR *q : queuePriorities)
{
// medium is considered the default if no priority is set otherwise
if(q->globalPriority > VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT)
q->globalPriority = VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT;
}
vkr = GetDeviceDispatchTable(NULL)->CreateDevice(Unwrap(physicalDevice), &createInfo, NULL,
&device);
}
if(vkr != VK_SUCCESS)
{
SET_ERROR_RESULT(m_FailedReplayResult, ResultCode::APIReplayFailed,
"Error creating logical device, VkResult: %s", ToStr(vkr).c_str());
return false;
}
GetResourceManager()->WrapResource(device, device);
GetResourceManager()->AddLiveResource(Device, device);
AddResource(Device, ResourceType::Device, "Device");
DerivedResource(origPhysDevice, Device);
// we unset the extension because it may be a 'shared' extension that's available at both instance
// and device. Only set it to enabled if it's really enabled for this device. This can happen with a
// device extension that is reported by another physical device than the one selected - it becomes
// available at instance level (e.g. for physical device queries) but is not available at *this*
// device level.
#undef CheckExt
#define CheckExt(name, ver) m_EnabledExtensions.ext_##name = false;
CheckDeviceExts();
uint32_t effectiveApiVersion = RDCMIN(m_EnabledExtensions.vulkanVersion, physProps.apiVersion);
#undef CheckExt
#define CheckExt(name, ver) \
if(effectiveApiVersion >= ver) \
{ \
m_EnabledExtensions.ext_##name = true; \
}
CheckDeviceExts();
#undef CheckExt
#define CheckExt(name, ver) \
if(!strcmp(createInfo.ppEnabledExtensionNames[i], "VK_" #name)) \
{ \
m_EnabledExtensions.ext_##name = true; \
}
for(uint32_t i = 0; i < createInfo.enabledExtensionCount; i++)
{
CheckDeviceExts();
}
// for cases where a promoted extension isn't supported as the extension itself, manually
// disable them when the feature bit is false.
if(effectiveApiVersion >= VK_MAKE_VERSION(1, 2, 0))
{
if(supportedExtensions.find(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME) ==
supportedExtensions.end() &&
!vulkan12Features.bufferDeviceAddress)
m_EnabledExtensions.ext_KHR_buffer_device_address = false;
if(supportedExtensions.find(VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME) ==
supportedExtensions.end() &&
!vulkan12Features.scalarBlockLayout)
m_EnabledExtensions.ext_EXT_scalar_block_layout = false;
if(supportedExtensions.find(VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME) ==
supportedExtensions.end() &&
!vulkan12Features.drawIndirectCount)
m_EnabledExtensions.ext_KHR_draw_indirect_count = false;
if(supportedExtensions.find(VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME) ==
supportedExtensions.end() &&
!vulkan12Features.samplerFilterMinmax)
m_EnabledExtensions.ext_EXT_sampler_filter_minmax = false;
// these features are required so this should never happen
if(supportedExtensions.find(VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_EXTENSION_NAME) ==
supportedExtensions.end() &&
!vulkan12Features.separateDepthStencilLayouts)
{
RDCWARN(
"Required feature 'separateDepthStencilLayouts' not supported by 1.2 physical device.");
m_EnabledExtensions.ext_KHR_separate_depth_stencil_layouts = false;
}
}
// we also need to check for feature enablement - if an extension is promoted that doesn't mean
// it's enabled
if(m_EnabledExtensions.ext_KHR_synchronization2)
{
if(!vulkan13Features.synchronization2 && !sync2.synchronization2)
m_EnabledExtensions.ext_KHR_synchronization2 = false;
}
InitInstanceExtensionTables(m_Instance, &m_EnabledExtensions);
InitDeviceExtensionTables(device, &m_EnabledExtensions);
RDCASSERT(m_Device == VK_NULL_HANDLE); // MULTIDEVICE
m_PhysicalDevice = physicalDevice;
m_Device = device;
m_QueueFamilyIdx = qFamilyIdx;
if(m_InternalCmds.cmdpool == VK_NULL_HANDLE)
{
VkCommandPoolCreateInfo poolInfo = {VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, NULL,
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
qFamilyIdx};
vkr = ObjDisp(device)->CreateCommandPool(Unwrap(device), &poolInfo, NULL,
&m_InternalCmds.cmdpool);
CheckVkResult(vkr);
GetResourceManager()->WrapResource(Unwrap(device), m_InternalCmds.cmdpool);
}
// for each queue family we've remapped to, ensure we have a command pool and command buffer on
// that queue, and we'll also use the first queue that the application creates (or fetch our
// own).
for(uint32_t i = 0; i < createInfo.queueCreateInfoCount; i++)
{
uint32_t qidx = createInfo.pQueueCreateInfos[i].queueFamilyIndex;
m_ExternalQueues.resize(RDCMAX((uint32_t)m_ExternalQueues.size(), qidx + 1));
ImageBarrierSequence::SetMaxQueueFamilyIndex(qidx);
VkCommandPoolCreateInfo poolInfo = {
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
NULL,
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
qidx,
};
vkr = ObjDisp(device)->CreateCommandPool(Unwrap(device), &poolInfo, NULL,
&m_ExternalQueues[qidx].pool);
CheckVkResult(vkr);
GetResourceManager()->WrapResource(Unwrap(device), m_ExternalQueues[qidx].pool);
VkCommandBufferAllocateInfo cmdInfo = {
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
NULL,
Unwrap(m_ExternalQueues[qidx].pool),
VK_COMMAND_BUFFER_LEVEL_PRIMARY,
1,
};
VkFenceCreateInfo fenceInfo = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, NULL,
VK_FENCE_CREATE_SIGNALED_BIT};
VkSemaphoreCreateInfo semInfo = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
for(size_t x = 0; x < ARRAY_COUNT(m_ExternalQueues[i].ring); x++)
{
vkr = ObjDisp(device)->AllocateCommandBuffers(Unwrap(device), &cmdInfo,
&m_ExternalQueues[qidx].ring[x].acquire);
CheckVkResult(vkr);
if(m_SetDeviceLoaderData)
m_SetDeviceLoaderData(device, m_ExternalQueues[qidx].ring[x].acquire);
else
SetDispatchTableOverMagicNumber(device, m_ExternalQueues[qidx].ring[x].acquire);
GetResourceManager()->WrapResource(Unwrap(device), m_ExternalQueues[qidx].ring[x].acquire);
vkr = ObjDisp(device)->AllocateCommandBuffers(Unwrap(device), &cmdInfo,
&m_ExternalQueues[qidx].ring[x].release);
CheckVkResult(vkr);
if(m_SetDeviceLoaderData)
m_SetDeviceLoaderData(device, m_ExternalQueues[qidx].ring[x].release);
else
SetDispatchTableOverMagicNumber(device, m_ExternalQueues[qidx].ring[x].release);
GetResourceManager()->WrapResource(Unwrap(device), m_ExternalQueues[qidx].ring[x].release);
vkr = ObjDisp(device)->CreateSemaphore(Unwrap(device), &semInfo, NULL,
&m_ExternalQueues[qidx].ring[x].fromext);
CheckVkResult(vkr);
GetResourceManager()->WrapResource(Unwrap(device), m_ExternalQueues[qidx].ring[x].fromext);
vkr = ObjDisp(device)->CreateSemaphore(Unwrap(device), &semInfo, NULL,
&m_ExternalQueues[qidx].ring[x].toext);
CheckVkResult(vkr);
GetResourceManager()->WrapResource(Unwrap(device), m_ExternalQueues[qidx].ring[x].toext);
vkr = ObjDisp(device)->CreateFence(Unwrap(device), &fenceInfo, NULL,
&m_ExternalQueues[qidx].ring[x].fence);
CheckVkResult(vkr);
GetResourceManager()->WrapResource(Unwrap(device), m_ExternalQueues[qidx].ring[x].fence);
}
}
m_Replay->SetDriverInformation(m_PhysicalDeviceData.props, m_PhysicalDeviceData.driverProps);
m_PhysicalDeviceData.enabledFeatures = enabledFeatures;
// MoltenVK reports 0x3fffffff for this limit so just ignore that value if it comes up
RDCASSERT(m_PhysicalDeviceData.props.limits.maxBoundDescriptorSets <
ARRAY_COUNT(BakedCmdBufferInfo::pushDescriptorID[0]) ||
m_PhysicalDeviceData.props.limits.maxBoundDescriptorSets >= 0x10000000,
m_PhysicalDeviceData.props.limits.maxBoundDescriptorSets);
m_PhysicalDeviceData.queueCount = (uint32_t)queueProps.size();
for(size_t i = 0; i < queueProps.size(); i++)
m_PhysicalDeviceData.queueProps[i] = queueProps[i];
if(RDCMIN(m_EnabledExtensions.vulkanVersion, physProps.apiVersion) >= VK_MAKE_VERSION(1, 1, 0))
{
VkPhysicalDeviceVulkan11Properties vulkan11Props = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES,
};
VkPhysicalDeviceProperties2 devProps2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2};
devProps2.pNext = &vulkan11Props;
ObjDisp(physicalDevice)->GetPhysicalDeviceProperties2(Unwrap(physicalDevice), &devProps2);
m_PhysicalDeviceData.maxMemoryAllocationSize = vulkan11Props.maxMemoryAllocationSize;
}
else
{
m_PhysicalDeviceData.maxMemoryAllocationSize = 0x80000000U;
}
ChooseMemoryIndices();
APIProps.vendor = GetDriverInfo().Vendor();
// temporarily disable the debug message sink, to ignore any false positive messages from our
// init
ScopedDebugMessageSink *sink = GetDebugMessageSink();
SetDebugMessageSink(NULL);
m_ShaderCache = new VulkanShaderCache(this);
m_DebugManager = new VulkanDebugManager(this);
m_Replay->CreateResources();
SetDebugMessageSink(sink);
}
return true;
}