Update vulkan format features in caps.
authoregdaniel <egdaniel@google.com>
Fri, 1 Apr 2016 17:10:45 +0000 (10:10 -0700)
committerCommit bot <commit-bot@chromium.org>
Fri, 1 Apr 2016 17:10:45 +0000 (10:10 -0700)
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1847963003

Review URL: https://codereview.chromium.org/1847963003

src/gpu/vk/GrVkCaps.cpp
src/gpu/vk/GrVkCaps.h
src/gpu/vk/GrVkGpu.cpp
src/gpu/vk/GrVkImage.cpp
src/gpu/vk/GrVkSampler.cpp

index 88ff8ee..7a1577e 100644 (file)
@@ -57,9 +57,8 @@ void GrVkCaps::init(const GrContextOptions& contextOptions, const GrVkInterface*
 
     this->initGrCaps(properties, memoryProperties, featureFlags);
     this->initGLSLCaps(properties, featureFlags);
-    this->initConfigTexturableTable(vkInterface, physDev);
-    this->initConfigRenderableTable(vkInterface, physDev);
-    this->initStencilFormats(vkInterface, physDev);
+    this->initConfigTable(vkInterface, physDev);
+    this->initStencilFormat(vkInterface, physDev);
 
     if (SkToBool(extensionFlags & kNV_glsl_shader_GrVkExtensionFlag)) {
         // Currently disabling this feature since it does not play well with validation layers which
@@ -162,122 +161,70 @@ void GrVkCaps::initGLSLCaps(const VkPhysicalDeviceProperties& properties,
                                             properties.limits.maxDescriptorSetSamplers);
 }
 
-static void format_supported_for_feature(const GrVkInterface* interface,
-                                         VkPhysicalDevice physDev,
-                                         VkFormat format,
-                                         VkFormatFeatureFlagBits featureBit,
-                                         bool* linearSupport,
-                                         bool* optimalSupport) {
+bool stencil_format_supported(const GrVkInterface* interface,
+                              VkPhysicalDevice physDev,
+                              VkFormat format) {
     VkFormatProperties props;
     memset(&props, 0, sizeof(VkFormatProperties));
     GR_VK_CALL(interface, GetPhysicalDeviceFormatProperties(physDev, format, &props));
-    *linearSupport = SkToBool(props.linearTilingFeatures & featureBit);
-    *optimalSupport = SkToBool(props.optimalTilingFeatures & featureBit);
+    return SkToBool(VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT & props.optimalTilingFeatures);
 }
 
-static void config_supported_for_feature(const GrVkInterface* interface,
-                                         VkPhysicalDevice physDev,
-                                         GrPixelConfig config,
-                                         VkFormatFeatureFlagBits featureBit,
-                                         bool* linearSupport,
-                                         bool* optimalSupport) {
-    VkFormat format;
-    if (!GrPixelConfigToVkFormat(config, &format)) {
-        *linearSupport = false;
-        *optimalSupport = false;
-        return;
+void GrVkCaps::initStencilFormat(const GrVkInterface* interface, VkPhysicalDevice physDev) {
+    // List of legal stencil formats (though perhaps not supported on
+    // the particular gpu/driver) from most preferred to least. We are guaranteed to have either
+    // VK_FORMAT_D24_UNORM_S8_UINT or VK_FORMAT_D24_SFLOAT_S8_UINT. VK_FORMAT_D32_SFLOAT_S8_UINT
+    // can optionally have 24 unused bits at the end so we assume the total bits is 64.
+    static const StencilFormat
+                  // internal Format             stencil bits      total bits        packed?
+        gS8    = { VK_FORMAT_S8_UINT,            8,                 8,               false },
+        gD24S8 = { VK_FORMAT_D24_UNORM_S8_UINT,  8,                32,               true },
+        gD32S8 = { VK_FORMAT_D32_SFLOAT_S8_UINT, 8,                64,               true };
+
+    if (stencil_format_supported(interface, physDev, VK_FORMAT_S8_UINT)) {
+        fPreferedStencilFormat = gS8;
+    } else if (stencil_format_supported(interface, physDev, VK_FORMAT_D24_UNORM_S8_UINT)) {
+        fPreferedStencilFormat = gD24S8;
+    } else {
+        SkASSERT(stencil_format_supported(interface, physDev, VK_FORMAT_D32_SFLOAT_S8_UINT));
+        fPreferedStencilFormat = gD32S8;
     }
-    format_supported_for_feature(interface, physDev, format, featureBit,
-                                 linearSupport, optimalSupport);
 }
 
-// Currently just assumeing if something can be rendered to without MSAA it also works for MSAAA
-#define SET_CONFIG_IS_RENDERABLE(config)                                                          \
-    config_supported_for_feature(interface,                                                       \
-                                 physDev,                                                         \
-                                 config,                                    \
-                                 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT,                    \
-                                 &fConfigLinearRenderSupport[config][kNo_MSAA],                   \
-                                 &fConfigRenderSupport[config][kNo_MSAA] );                       \
-    fConfigRenderSupport[config][kYes_MSAA] = fConfigRenderSupport[config][kNo_MSAA];             \
-    fConfigLinearRenderSupport[config][kYes_MSAA] = fConfigLinearRenderSupport[config][kNo_MSAA];
-
-
-void GrVkCaps::initConfigRenderableTable(const GrVkInterface* interface, VkPhysicalDevice physDev) {
-    enum {
-        kNo_MSAA = 0,
-        kYes_MSAA = 1,
-    };
-
-    // Base render support
-    SET_CONFIG_IS_RENDERABLE(kAlpha_8_GrPixelConfig);
-    SET_CONFIG_IS_RENDERABLE(kRGB_565_GrPixelConfig);
-    SET_CONFIG_IS_RENDERABLE(kRGBA_4444_GrPixelConfig);
-    SET_CONFIG_IS_RENDERABLE(kRGBA_8888_GrPixelConfig);
-    SET_CONFIG_IS_RENDERABLE(kBGRA_8888_GrPixelConfig);
-
-    SET_CONFIG_IS_RENDERABLE(kSRGBA_8888_GrPixelConfig);
-
-    // Float render support
-    SET_CONFIG_IS_RENDERABLE(kRGBA_float_GrPixelConfig);
-    SET_CONFIG_IS_RENDERABLE(kRGBA_half_GrPixelConfig);
-    SET_CONFIG_IS_RENDERABLE(kAlpha_half_GrPixelConfig);
+void GrVkCaps::initConfigTable(const GrVkInterface* interface, VkPhysicalDevice physDev) {
+    for (int i = 0; i < kGrPixelConfigCnt; ++i) {
+        VkFormat format;
+        if (GrPixelConfigToVkFormat(static_cast<GrPixelConfig>(i), &format)) {
+            fConfigTable[i].init(interface, physDev, format);
+        }
+    }
 }
 
-#define SET_CONFIG_IS_TEXTURABLE(config)                                 \
-    config_supported_for_feature(interface,                              \
-                                 physDev,                                \
-                                 config,                                 \
-                                 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT,    \
-                                 &fConfigLinearTextureSupport[config],   \
-                                 &fConfigTextureSupport[config]);
-
-void GrVkCaps::initConfigTexturableTable(const GrVkInterface* interface, VkPhysicalDevice physDev) {
-    // Base texture support
-    SET_CONFIG_IS_TEXTURABLE(kAlpha_8_GrPixelConfig);
-    SET_CONFIG_IS_TEXTURABLE(kRGB_565_GrPixelConfig);
-    SET_CONFIG_IS_TEXTURABLE(kRGBA_4444_GrPixelConfig);
-    SET_CONFIG_IS_TEXTURABLE(kRGBA_8888_GrPixelConfig);
-    SET_CONFIG_IS_TEXTURABLE(kBGRA_8888_GrPixelConfig);
-
-    SET_CONFIG_IS_TEXTURABLE(kIndex_8_GrPixelConfig);
-    SET_CONFIG_IS_TEXTURABLE(kSRGBA_8888_GrPixelConfig);
-
-    // Compressed texture support
-    SET_CONFIG_IS_TEXTURABLE(kETC1_GrPixelConfig);
-    SET_CONFIG_IS_TEXTURABLE(kLATC_GrPixelConfig);
-    SET_CONFIG_IS_TEXTURABLE(kR11_EAC_GrPixelConfig);
-    SET_CONFIG_IS_TEXTURABLE(kASTC_12x12_GrPixelConfig);
-
-    // Float texture support
-    SET_CONFIG_IS_TEXTURABLE(kRGBA_float_GrPixelConfig);
-    SET_CONFIG_IS_TEXTURABLE(kRGBA_half_GrPixelConfig);
-    SET_CONFIG_IS_TEXTURABLE(kAlpha_half_GrPixelConfig);
-}
+void GrVkCaps::ConfigInfo::InitConfigFlags(VkFormatFeatureFlags vkFlags, uint16_t* flags) {
+    if (SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT & vkFlags) &&
+        SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT & vkFlags)) {
+        *flags = *flags | kTextureable_Flag;
+    }
 
-#define SET_CONFIG_CAN_STENCIL(config)                                                    \
-    bool SK_MACRO_APPEND_LINE(linearSupported);                                           \
-    bool SK_MACRO_APPEND_LINE(optimalSupported);                                          \
-    format_supported_for_feature(interface,                                               \
-                                 physDev,                                                 \
-                                 config.fInternalFormat,                                  \
-                                 VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT,          \
-                                 &SK_MACRO_APPEND_LINE(linearSupported),                  \
-                                 &SK_MACRO_APPEND_LINE(optimalSupported));                \
-    if (SK_MACRO_APPEND_LINE(linearSupported)) fLinearStencilFormats.push_back(config);   \
-    if (SK_MACRO_APPEND_LINE(optimalSupported)) fStencilFormats.push_back(config);
-
-void GrVkCaps::initStencilFormats(const GrVkInterface* interface, VkPhysicalDevice physDev) {
-    // Build up list of legal stencil formats (though perhaps not supported on
-    // the particular gpu/driver) from most preferred to least.
+    if (SkToBool(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT & vkFlags)) {
+        *flags = *flags | kRenderable_Flag;
+    }
 
-    static const StencilFormat
-                  // internal Format             stencil bits      total bits        packed?
-        gS8    = { VK_FORMAT_S8_UINT,            8,                 8,               false },
-        gD24S8 = { VK_FORMAT_D24_UNORM_S8_UINT,  8,                32,               true };
+    if (SkToBool(VK_FORMAT_FEATURE_BLIT_SRC_BIT & vkFlags)) {
+        *flags = *flags | kBlitSrc_Flag;
+    }
 
-    // I'm simply assuming that these two will be supported since they are used in example code.
-    // TODO: Actaully figure this out
-    SET_CONFIG_CAN_STENCIL(gS8);
-    SET_CONFIG_CAN_STENCIL(gD24S8);
+    if (SkToBool(VK_FORMAT_FEATURE_BLIT_DST_BIT & vkFlags)) {
+        *flags = *flags | kBlitDst_Flag;
+    }
+}
+
+void GrVkCaps::ConfigInfo::init(const GrVkInterface* interface,
+                                VkPhysicalDevice physDev,
+                                VkFormat format) {
+    VkFormatProperties props;
+    memset(&props, 0, sizeof(VkFormatProperties));
+    GR_VK_CALL(interface, GetPhysicalDeviceFormatProperties(physDev, format, &props));
+    InitConfigFlags(props.linearTilingFeatures, &fLinearFlags);
+    InitConfigFlags(props.optimalTilingFeatures, &fOptimalFlags);
 }
index 5834b15..0bd3801 100644 (file)
@@ -31,42 +31,48 @@ public:
 
     bool isConfigTexturable(GrPixelConfig config) const override {
         SkASSERT(kGrPixelConfigCnt > config);
-        return fConfigTextureSupport[config];
+        return SkToBool(ConfigInfo::kTextureable_Flag & fConfigTable[config].fOptimalFlags);
     }
 
     bool isConfigRenderable(GrPixelConfig config, bool withMSAA) const override {
         SkASSERT(kGrPixelConfigCnt > config);
-        return fConfigRenderSupport[config][withMSAA];
+        return SkToBool(ConfigInfo::kRenderable_Flag & fConfigTable[config].fOptimalFlags);
+    }
+
+    bool isConfigTexurableLinearly(GrPixelConfig config) const {
+        SkASSERT(kGrPixelConfigCnt > config);
+        return SkToBool(ConfigInfo::kTextureable_Flag & fConfigTable[config].fLinearFlags);
     }
 
     bool isConfigRenderableLinearly(GrPixelConfig config, bool withMSAA) const {
         SkASSERT(kGrPixelConfigCnt > config);
-        return fConfigLinearRenderSupport[config][withMSAA];
+        return !withMSAA && SkToBool(ConfigInfo::kRenderable_Flag &
+                                     fConfigTable[config].fLinearFlags);
     }
 
-    bool isConfigTexurableLinearly(GrPixelConfig config) const {
+    bool configCanBeDstofBlit(GrPixelConfig config, bool linearTiled) const {
         SkASSERT(kGrPixelConfigCnt > config);
-        return fConfigLinearTextureSupport[config];
+        const uint16_t& flags = linearTiled ? fConfigTable[config].fLinearFlags :
+                                              fConfigTable[config].fOptimalFlags;
+        return SkToBool(ConfigInfo::kBlitDst_Flag & flags);
     }
 
-    bool canUseGLSLForShaderModule() const {
-        return fCanUseGLSLForShaderModule;
+    bool configCanBeSrcofBlit(GrPixelConfig config, bool linearTiled) const {
+        SkASSERT(kGrPixelConfigCnt > config);
+        const uint16_t& flags = linearTiled ? fConfigTable[config].fLinearFlags :
+                                              fConfigTable[config].fOptimalFlags;
+        return SkToBool(ConfigInfo::kBlitSrc_Flag & flags);
     }
 
-    /**
-     * Gets an array of legal stencil formats. These formats are not guaranteed to be supported by
-     * the driver but are legal VK_TEXTURE_FORMATs.
-     */
-    const SkTArray<StencilFormat, true>& stencilFormats() const {
-        return fStencilFormats;
+    bool canUseGLSLForShaderModule() const {
+        return fCanUseGLSLForShaderModule;
     }
 
     /**
-     * Gets an array of legal stencil formats. These formats are not guaranteed to be supported by
-     * the driver but are legal VK_TEXTURE_FORMATs.
+     * Returns both a supported and most prefered stencil format to use in draws.
      */
-    const SkTArray<StencilFormat, true>& linearStencilFormats() const {
-        return fLinearStencilFormats;
+    const StencilFormat& preferedStencilFormat() const {
+        return fPreferedStencilFormat;
     }
 
     GrGLSLCaps* glslCaps() const { return reinterpret_cast<GrGLSLCaps*>(fShaderCaps.get()); }
@@ -79,22 +85,30 @@ private:
                     uint32_t featureFlags);
     void initGLSLCaps(const VkPhysicalDeviceProperties&, uint32_t featureFlags);
     void initSampleCount(const VkPhysicalDeviceProperties& properties);
-    void initConfigRenderableTable(const GrVkInterface* iface, VkPhysicalDevice physDev);
-    void initConfigTexturableTable(const GrVkInterface* iface, VkPhysicalDevice physDev);
-    void initStencilFormats(const GrVkInterface* iface, VkPhysicalDevice physDev);
 
 
-    bool fConfigTextureSupport[kGrPixelConfigCnt];
-    // For Vulkan we track whether a config is supported linearly (without need for swizzling)
-    bool fConfigLinearTextureSupport[kGrPixelConfigCnt];
+    void initConfigTable(const GrVkInterface*, VkPhysicalDevice);
+    void initStencilFormat(const GrVkInterface* iface, VkPhysicalDevice physDev);
+
+    struct ConfigInfo {
+        ConfigInfo() : fOptimalFlags(0), fLinearFlags(0) {}
+
+        void init(const GrVkInterface*, VkPhysicalDevice, VkFormat);
+        static void InitConfigFlags(VkFormatFeatureFlags, uint16_t* flags);
 
-    // The first entry for each config is without msaa and the second is with.
-    bool fConfigRenderSupport[kGrPixelConfigCnt][2];
-    // The first entry for each config is without msaa and the second is with.
-    bool fConfigLinearRenderSupport[kGrPixelConfigCnt][2];
+        enum {
+            kTextureable_Flag = 0x1,
+            kRenderable_Flag  = 0x2,
+            kBlitSrc_Flag     = 0x4,
+            kBlitDst_Flag     = 0x8,
+        };
 
-    SkTArray<StencilFormat, true> fLinearStencilFormats;
-    SkTArray<StencilFormat, true> fStencilFormats;
+        uint16_t fOptimalFlags;
+        uint16_t fLinearFlags;
+    };
+    ConfigInfo fConfigTable[kGrPixelConfigCnt];
+    
+    StencilFormat fPreferedStencilFormat;
 
     // Tells of if we can pass in straight GLSL string into vkCreateShaderModule
     bool fCanUseGLSLForShaderModule;
index de1e905..55f1eae 100644 (file)
@@ -650,8 +650,7 @@ GrStencilAttachment* GrVkGpu::createStencilAttachmentForRenderTarget(const GrRen
 
     int samples = rt->numStencilSamples();
 
-    SkASSERT(this->vkCaps().stencilFormats().count());
-    const GrVkCaps::StencilFormat& sFmt = this->vkCaps().stencilFormats()[0];
+    const GrVkCaps::StencilFormat& sFmt = this->vkCaps().preferedStencilFormat();
 
     GrVkStencilAttachment* stencil(GrVkStencilAttachment::Create(this,
                                                                  GrGpuResource::kCached_LifeCycle,
index f91c6a9..7413630 100644 (file)
@@ -58,6 +58,10 @@ const GrVkImage::Resource* GrVkImage::CreateResource(const GrVkGpu* gpu,
     if (!GrSampleCountToVkSampleCount(imageDesc.fSamples, &vkSamples)) {
         return nullptr;
     }
+
+    SkASSERT(VK_IMAGE_TILING_OPTIMAL == imageDesc.fImageTiling ||
+             VK_SAMPLE_COUNT_1_BIT == vkSamples);
+
     const VkImageCreateInfo imageCreateInfo = {
         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,         // sType
         NULL,                                        // pNext
index fb8daca..75c2ee8 100644 (file)
@@ -52,6 +52,11 @@ GrVkSampler* GrVkSampler::Create(const GrVkGpu* gpu, const GrTextureParams& para
     createInfo.maxAnisotropy = 1.0f;
     createInfo.compareEnable = VK_FALSE;
     createInfo.compareOp = VK_COMPARE_OP_NEVER;
+    // Vulkan doesn't have a direct mapping of GL's nearest or linear filters for minFilter since
+    // there is always a mipmapMode. To get the same effect as GL we can set minLod = maxLod = 0.0.
+    // This works since our min and mag filters are the same (this forces us to use mag on the 0
+    // level mip). If the filters weren't the same we could set min = 0 and max = 0.25 to force
+    // the minFilter on mip level 0.
     createInfo.minLod = 0.0f;
     createInfo.maxLod = 0.0f;
     createInfo.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;