If format doesn't support bits we want, return unsupported. Closes #1098

* The only formats the spec requires are for optimalTiledFeatures and already
  requires all the usage bits we are going to enable ourselves. The only cases
  where we can get in trouble is for formats that support a subset of those
  features e.g. on linear tiled images.
* So we can safely remove the reported support for those formats and still be
  compliant. The application must then work with that lack of support the same
  way as it would do if the ICD itself didn't have that support.
This commit is contained in:
baldurk
2018-09-05 10:58:28 +01:00
parent 40c3a735a4
commit ca462ab03f
+103 -20
View File
@@ -52,6 +52,51 @@ void WrappedVulkan::vkGetPhysicalDeviceFormatProperties(VkPhysicalDevice physica
{
ObjDisp(physicalDevice)
->GetPhysicalDeviceFormatProperties(Unwrap(physicalDevice), format, pFormatProperties);
// we require all these properties at minimum for an image to be created, since we add these to
// any usage. Fortunately, in the formats the spec requires an implementation to support,
// optimalTiledFeatures must contain all these and more, so we can safely remove support for any
// format that only includes a subset.
uint32_t minRequiredMask = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
const InstanceDeviceInfo &exts = GetExtensions(GetRecord(physicalDevice));
// transfer src/dst bits were added in KHR_maintenance1. Before then we assume that if
// SAMPLED_IMAGE_BIT was present it's safe to add the transfer bits too.
if(exts.ext_KHR_maintenance1)
minRequiredMask |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
if((pFormatProperties->linearTilingFeatures & minRequiredMask) != minRequiredMask)
pFormatProperties->linearTilingFeatures = 0;
if((pFormatProperties->optimalTilingFeatures & minRequiredMask) != minRequiredMask)
pFormatProperties->optimalTilingFeatures = 0;
}
void WrappedVulkan::vkGetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,
VkFormat format,
VkFormatProperties2 *pFormatProperties)
{
ObjDisp(physicalDevice)
->GetPhysicalDeviceFormatProperties2(Unwrap(physicalDevice), format, pFormatProperties);
// we require transfer source and dest these properties at minimum for an image to be created,
// since we add these to
// any usage. Fortunately, in the formats the spec requires an implementation to support,
// optimalTiledFeatures must contain all these and more, so we can safely remove support for any
// format that only includes a subset.
uint32_t minRequiredMask = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
const InstanceDeviceInfo &exts = GetExtensions(GetRecord(physicalDevice));
// transfer src/dst bits were added in KHR_maintenance1. Before then we assume that if
// SAMPLED_IMAGE_BIT was present it's safe to add the transfer bits too.
if(exts.ext_KHR_maintenance1)
minRequiredMask |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
if((pFormatProperties->formatProperties.linearTilingFeatures & minRequiredMask) != minRequiredMask)
pFormatProperties->formatProperties.linearTilingFeatures = 0;
if((pFormatProperties->formatProperties.optimalTilingFeatures & minRequiredMask) != minRequiredMask)
pFormatProperties->formatProperties.optimalTilingFeatures = 0;
}
VkResult WrappedVulkan::vkGetPhysicalDeviceImageFormatProperties(
@@ -59,9 +104,64 @@ VkResult WrappedVulkan::vkGetPhysicalDeviceImageFormatProperties(
VkImageUsageFlags usage, VkImageCreateFlags flags,
VkImageFormatProperties *pImageFormatProperties)
{
return ObjDisp(physicalDevice)
->GetPhysicalDeviceImageFormatProperties(Unwrap(physicalDevice), format, type, tiling, usage,
flags, pImageFormatProperties);
// we're going to add these usage bits implicitly on image create, so ensure we get an accurate
// response by adding them here. It's OK to add these, since these can't make a required format
// suddenly report as unsupported (all required formats must support these usages), so it can only
// make an optional format unsupported which is what we want.
usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_SAMPLED_BIT;
VkResult vkr =
ObjDisp(physicalDevice)
->GetPhysicalDeviceImageFormatProperties(Unwrap(physicalDevice), format, type, tiling,
usage, flags, pImageFormatProperties);
if(vkr == VK_SUCCESS)
{
// check that the format is one we allow to be supported - if not we return an error to be
// consistent.
VkFormatProperties props;
vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &props);
if(props.linearTilingFeatures == 0 && props.optimalTilingFeatures == 0)
{
RDCEraseEl(*pImageFormatProperties);
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
}
return vkr;
}
VkResult WrappedVulkan::vkGetPhysicalDeviceImageFormatProperties2(
VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo,
VkImageFormatProperties2 *pImageFormatProperties)
{
// we're going to add these usage bits implicitly on image create, so ensure we get an accurate
// response by adding them here. It's OK to add these, since these can't make a required format
// suddenly report as unsupported (all required formats must support these usages), so it can only
// make an optional format unsupported which is what we want.
VkPhysicalDeviceImageFormatInfo2 info = *pImageFormatInfo;
info.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_SAMPLED_BIT;
VkResult vkr = ObjDisp(physicalDevice)
->GetPhysicalDeviceImageFormatProperties2(Unwrap(physicalDevice), &info,
pImageFormatProperties);
if(vkr == VK_SUCCESS)
{
// check that the format is one we allow to be supported - if not we return an error to be
// consistent.
VkFormatProperties props;
vkGetPhysicalDeviceFormatProperties(physicalDevice, pImageFormatInfo->format, &props);
if(props.linearTilingFeatures == 0 && props.optimalTilingFeatures == 0)
{
RDCEraseEl(pImageFormatProperties->imageFormatProperties);
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
}
return vkr;
}
void WrappedVulkan::vkGetPhysicalDeviceSparseImageFormatProperties(
@@ -456,23 +556,6 @@ void WrappedVulkan::vkGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevi
return ObjDisp(physicalDevice)->GetPhysicalDeviceProperties2(Unwrap(physicalDevice), pProperties);
}
void WrappedVulkan::vkGetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,
VkFormat format,
VkFormatProperties2 *pFormatProperties)
{
return ObjDisp(physicalDevice)
->GetPhysicalDeviceFormatProperties2(Unwrap(physicalDevice), format, pFormatProperties);
}
VkResult WrappedVulkan::vkGetPhysicalDeviceImageFormatProperties2(
VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo,
VkImageFormatProperties2 *pImageFormatProperties)
{
return ObjDisp(physicalDevice)
->GetPhysicalDeviceImageFormatProperties2(Unwrap(physicalDevice), pImageFormatInfo,
pImageFormatProperties);
}
void WrappedVulkan::vkGetPhysicalDeviceQueueFamilyProperties2(
VkPhysicalDevice physicalDevice, uint32_t *pCount,
VkQueueFamilyProperties2 *pQueueFamilyProperties)