Update gpu caps for valid sample counts.

Instead of query and maxSampleCount and using that to cap, we now have
each config store its supported values and when requested returns either
the next highest or equal supported value, or if non the max config supported.

Bug: skia:
Change-Id: I8802d44c13b3b1703ee54a7e69b82102d4b8dc2d
Reviewed-on: https://skia-review.googlesource.com/24302
Commit-Queue: Greg Daniel <egdaniel@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp
index db92617..909b4fb 100644
--- a/src/gpu/vk/GrVkCaps.cpp
+++ b/src/gpu/vk/GrVkCaps.cpp
@@ -340,6 +340,47 @@
     }
 }
 
+void GrVkCaps::ConfigInfo::initSampleCounts(const GrVkInterface* interface,
+                                            VkPhysicalDevice physDev,
+                                            VkFormat format) {
+    VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
+                              VK_IMAGE_USAGE_TRANSFER_DST_BIT |
+                              VK_IMAGE_USAGE_SAMPLED_BIT |
+                              VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+    VkImageCreateFlags createFlags = GrVkFormatIsSRGB(format, nullptr)
+        ? VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT : 0;
+    VkImageFormatProperties properties;
+    GR_VK_CALL(interface, GetPhysicalDeviceImageFormatProperties(physDev,
+                                                                 format,
+                                                                 VK_IMAGE_TYPE_2D,
+                                                                 VK_IMAGE_TILING_OPTIMAL,
+                                                                 usage,
+                                                                 createFlags,
+                                                                 &properties));
+    VkSampleCountFlags flags = properties.sampleCounts;
+    if (flags & VK_SAMPLE_COUNT_1_BIT) {
+        fColorSampleCounts.push(0);
+    }
+    if (flags & VK_SAMPLE_COUNT_2_BIT) {
+        fColorSampleCounts.push(2);
+    }
+    if (flags & VK_SAMPLE_COUNT_4_BIT) {
+        fColorSampleCounts.push(4);
+    }
+    if (flags & VK_SAMPLE_COUNT_8_BIT) {
+        fColorSampleCounts.push(8);
+    }
+    if (flags & VK_SAMPLE_COUNT_16_BIT) {
+        fColorSampleCounts.push(16);
+    }
+    if (flags & VK_SAMPLE_COUNT_32_BIT) {
+        fColorSampleCounts.push(32);
+    }
+    if (flags & VK_SAMPLE_COUNT_64_BIT) {
+        fColorSampleCounts.push(64);
+    }
+}
+
 void GrVkCaps::ConfigInfo::init(const GrVkInterface* interface,
                                 VkPhysicalDevice physDev,
                                 VkFormat format) {
@@ -348,4 +389,22 @@
     GR_VK_CALL(interface, GetPhysicalDeviceFormatProperties(physDev, format, &props));
     InitConfigFlags(props.linearTilingFeatures, &fLinearFlags);
     InitConfigFlags(props.optimalTilingFeatures, &fOptimalFlags);
+    if (fOptimalFlags & kRenderable_Flag) {
+        this->initSampleCounts(interface, physDev, format);
+    }
 }
+
+int GrVkCaps::getSampleCount(int requestedCount, GrPixelConfig config) const {
+    int count = fConfigTable[config].fColorSampleCounts.count();
+    if (!count || !this->isConfigRenderable(config, true)) {
+        return 0;
+    }
+
+    for (int i = 0; i < count; ++i) {
+        if (fConfigTable[config].fColorSampleCounts[i] >= requestedCount) {
+            return fConfigTable[config].fColorSampleCounts[i];
+        }
+    }
+    return fConfigTable[config].fColorSampleCounts[count-1];
+}
+
diff --git a/src/gpu/vk/GrVkCaps.h b/src/gpu/vk/GrVkCaps.h
index f599d22..b085486 100644
--- a/src/gpu/vk/GrVkCaps.h
+++ b/src/gpu/vk/GrVkCaps.h
@@ -29,6 +29,8 @@
     GrVkCaps(const GrContextOptions& contextOptions, const GrVkInterface* vkInterface,
              VkPhysicalDevice device, uint32_t featureFlags, uint32_t extensionFlags);
 
+    int getSampleCount(int requestedCount, GrPixelConfig config) const override;
+
     bool isConfigTexturable(GrPixelConfig config) const override {
         return SkToBool(ConfigInfo::kTextureable_Flag & fConfigTable[config].fOptimalFlags);
     }
@@ -132,6 +134,7 @@
 
         void init(const GrVkInterface*, VkPhysicalDevice, VkFormat);
         static void InitConfigFlags(VkFormatFeatureFlags, uint16_t* flags);
+        void initSampleCounts(const GrVkInterface*, VkPhysicalDevice, VkFormat);
 
         enum {
             kTextureable_Flag = 0x1,
@@ -142,6 +145,8 @@
 
         uint16_t fOptimalFlags;
         uint16_t fLinearFlags;
+
+        SkTDArray<int> fColorSampleCounts;
     };
     ConfigInfo fConfigTable[kGrPixelConfigCnt];
 
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index 17fccfb..cd0fc99 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -882,7 +882,7 @@
     surfDesc.fWidth = backendTex.width();
     surfDesc.fHeight = backendTex.height();
     surfDesc.fConfig = backendTex.config();
-    surfDesc.fSampleCnt = SkTMin(sampleCnt, this->caps()->maxSampleCount());
+    surfDesc.fSampleCnt = this->caps()->getSampleCount(sampleCnt, backendTex.config());
     bool renderTarget = SkToBool(flags & kRenderTarget_GrBackendTextureFlag);
     // In GL, Chrome assumes all textures are BottomLeft
     // In VK, we don't have this restriction
@@ -948,7 +948,7 @@
     desc.fConfig = tex.config();
     desc.fWidth = tex.width();
     desc.fHeight = tex.height();
-    desc.fSampleCnt = SkTMin(sampleCnt, this->caps()->maxSampleCount());
+    desc.fSampleCnt = this->caps()->getSampleCount(sampleCnt, tex.config());
 
     desc.fOrigin = resolve_origin(origin);