Home | History | Annotate | Download | only in vk
      1 /*
      2  * Copyright 2015 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "GrVkCaps.h"
      9 
     10 #include "GrVkUtil.h"
     11 #include "glsl/GrGLSLCaps.h"
     12 #include "vk/GrVkInterface.h"
     13 
     14 GrVkCaps::GrVkCaps(const GrContextOptions& contextOptions, const GrVkInterface* vkInterface,
     15                    VkPhysicalDevice physDev) : INHERITED(contextOptions) {
     16     /**************************************************************************
     17     * GrDrawTargetCaps fields
     18     **************************************************************************/
     19     fMipMapSupport = false; //TODO: figure this out
     20     fNPOTTextureTileSupport = false; //TODO: figure this out
     21     fTwoSidedStencilSupport = false; //TODO: figure this out
     22     fStencilWrapOpsSupport = false; //TODO: figure this out
     23     fDiscardRenderTargetSupport = false; //TODO: figure this out
     24     fReuseScratchTextures = true; //TODO: figure this out
     25     fGpuTracingSupport = false; //TODO: figure this out
     26     fCompressedTexSubImageSupport = false; //TODO: figure this out
     27     fOversizedStencilSupport = false; //TODO: figure this out
     28 
     29     fUseDrawInsteadOfClear = false; //TODO: figure this out
     30 
     31     fMapBufferFlags = kNone_MapFlags; //TODO: figure this out
     32     fGeometryBufferMapThreshold = SK_MaxS32;  //TODO: figure this out
     33 
     34     fMaxRenderTargetSize = 4096; // minimum required by spec
     35     fMaxTextureSize = 4096; // minimum required by spec
     36     fMaxColorSampleCount = 4; // minimum required by spec
     37     fMaxStencilSampleCount = 4; // minimum required by spec
     38 
     39 
     40     fShaderCaps.reset(new GrGLSLCaps(contextOptions));
     41 
     42     /**************************************************************************
     43     * GrVkCaps fields
     44     **************************************************************************/
     45     fMaxSampledTextures = 16; // Spec requires a minimum of 16 sampled textures per stage
     46 
     47     this->init(contextOptions, vkInterface, physDev);
     48 }
     49 
     50 void GrVkCaps::init(const GrContextOptions& contextOptions, const GrVkInterface* vkInterface,
     51                     VkPhysicalDevice physDev) {
     52 
     53     this->initGLSLCaps(vkInterface, physDev);
     54     this->initConfigTexturableTable(vkInterface, physDev);
     55     this->initConfigRenderableTable(vkInterface, physDev);
     56     this->initStencilFormats(vkInterface, physDev);
     57 
     58     VkPhysicalDeviceProperties properties;
     59     GR_VK_CALL(vkInterface, GetPhysicalDeviceProperties(physDev, &properties));
     60 
     61     // We could actually querey and get a max size for each config, however maxImageDimension2D will
     62     // give the minimum max size across all configs. So for simplicity we will use that for now.
     63     fMaxRenderTargetSize = properties.limits.maxImageDimension2D;
     64     fMaxTextureSize = properties.limits.maxImageDimension2D;
     65 
     66     this->initSampleCount(properties);
     67 
     68     fMaxSampledTextures = SkTMin(properties.limits.maxPerStageDescriptorSampledImages,
     69                                  properties.limits.maxPerStageDescriptorSamplers);
     70 
     71     this->applyOptionsOverrides(contextOptions);
     72     // need to friend GrVkCaps in GrGLSLCaps.h
     73     // GrGLSLCaps* glslCaps = static_cast<GrGLSLCaps*>(fShaderCaps.get());
     74     // glslCaps->applyOptionsOverrides(contextOptions);
     75 }
     76 
     77 int get_max_sample_count(VkSampleCountFlags flags) {
     78     SkASSERT(flags & VK_SAMPLE_COUNT_1_BIT);
     79     if (!(flags & VK_SAMPLE_COUNT_2_BIT)) {
     80         return 0;
     81     }
     82     if (!(flags & VK_SAMPLE_COUNT_4_BIT)) {
     83         return 2;
     84     }
     85     if (!(flags & VK_SAMPLE_COUNT_8_BIT)) {
     86         return 4;
     87     }
     88     if (!(flags & VK_SAMPLE_COUNT_16_BIT)) {
     89         return 8;
     90     }
     91     if (!(flags & VK_SAMPLE_COUNT_32_BIT)) {
     92         return 16;
     93     }
     94     if (!(flags & VK_SAMPLE_COUNT_64_BIT)) {
     95         return 32;
     96     }
     97     return 64;
     98 }
     99 
    100 void GrVkCaps::initSampleCount(const VkPhysicalDeviceProperties& properties) {
    101     VkSampleCountFlags colorSamples = properties.limits.framebufferColorSampleCounts;
    102     VkSampleCountFlags stencilSamples = properties.limits.framebufferStencilSampleCounts;
    103 
    104     fMaxColorSampleCount = get_max_sample_count(colorSamples);
    105     fMaxStencilSampleCount = get_max_sample_count(stencilSamples);
    106 }
    107 
    108 void GrVkCaps::initGLSLCaps(const GrVkInterface* interface, VkPhysicalDevice physDev) {
    109     GrGLSLCaps* glslCaps = static_cast<GrGLSLCaps*>(fShaderCaps.get());
    110     // TODO: actually figure out a correct version here
    111     glslCaps->fVersionDeclString = "#version 140\n";
    112 
    113     // fConfigOutputSwizzle will default to RGBA so we only need to set it for alpha only config.
    114     for (int i = 0; i < kGrPixelConfigCnt; ++i) {
    115         GrPixelConfig config = static_cast<GrPixelConfig>(i);
    116         if (GrPixelConfigIsAlphaOnly(config)) {
    117             glslCaps->fConfigTextureSwizzle[i] = GrSwizzle::RRRR();
    118             glslCaps->fConfigOutputSwizzle[i] = GrSwizzle::AAAA();
    119         } else {
    120             glslCaps->fConfigTextureSwizzle[i] = GrSwizzle::RGBA();
    121         }
    122     }
    123 }
    124 
    125 static void format_supported_for_feature(const GrVkInterface* interface,
    126                                          VkPhysicalDevice physDev,
    127                                          VkFormat format,
    128                                          VkFormatFeatureFlagBits featureBit,
    129                                          bool* linearSupport,
    130                                          bool* optimalSupport) {
    131     VkFormatProperties props;
    132     memset(&props, 0, sizeof(VkFormatProperties));
    133     GR_VK_CALL(interface, GetPhysicalDeviceFormatProperties(physDev, format, &props));
    134     *linearSupport = SkToBool(props.linearTilingFeatures & featureBit);
    135     *optimalSupport = SkToBool(props.optimalTilingFeatures & featureBit);
    136 }
    137 
    138 static void config_supported_for_feature(const GrVkInterface* interface,
    139                                          VkPhysicalDevice physDev,
    140                                          GrPixelConfig config,
    141                                          VkFormatFeatureFlagBits featureBit,
    142                                          bool* linearSupport,
    143                                          bool* optimalSupport) {
    144     VkFormat format;
    145     if (!GrPixelConfigToVkFormat(config, &format)) {
    146         *linearSupport = false;
    147         *optimalSupport = false;
    148         return;
    149     }
    150     format_supported_for_feature(interface, physDev, format, featureBit,
    151                                  linearSupport, optimalSupport);
    152 }
    153 
    154 // Currently just assumeing if something can be rendered to without MSAA it also works for MSAAA
    155 #define SET_CONFIG_IS_RENDERABLE(config)                                                          \
    156     config_supported_for_feature(interface,                                                       \
    157                                  physDev,                                                         \
    158                                  config,                                    \
    159                                  VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT,                    \
    160                                  &fConfigLinearRenderSupport[config][kNo_MSAA],                   \
    161                                  &fConfigRenderSupport[config][kNo_MSAA] );                       \
    162     fConfigRenderSupport[config][kYes_MSAA] = fConfigRenderSupport[config][kNo_MSAA];             \
    163     fConfigLinearRenderSupport[config][kYes_MSAA] = fConfigLinearRenderSupport[config][kNo_MSAA];
    164 
    165 
    166 void GrVkCaps::initConfigRenderableTable(const GrVkInterface* interface, VkPhysicalDevice physDev) {
    167     enum {
    168         kNo_MSAA = 0,
    169         kYes_MSAA = 1,
    170     };
    171 
    172     // Base render support
    173     SET_CONFIG_IS_RENDERABLE(kAlpha_8_GrPixelConfig);
    174     SET_CONFIG_IS_RENDERABLE(kRGB_565_GrPixelConfig);
    175     SET_CONFIG_IS_RENDERABLE(kRGBA_4444_GrPixelConfig);
    176     SET_CONFIG_IS_RENDERABLE(kRGBA_8888_GrPixelConfig);
    177     SET_CONFIG_IS_RENDERABLE(kBGRA_8888_GrPixelConfig);
    178 
    179     SET_CONFIG_IS_RENDERABLE(kSRGBA_8888_GrPixelConfig);
    180 
    181     // Float render support
    182     SET_CONFIG_IS_RENDERABLE(kRGBA_float_GrPixelConfig);
    183     SET_CONFIG_IS_RENDERABLE(kRGBA_half_GrPixelConfig);
    184     SET_CONFIG_IS_RENDERABLE(kAlpha_half_GrPixelConfig);
    185 }
    186 
    187 #define SET_CONFIG_IS_TEXTURABLE(config)                                 \
    188     config_supported_for_feature(interface,                              \
    189                                  physDev,                                \
    190                                  config,                                 \
    191                                  VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT,    \
    192                                  &fConfigLinearTextureSupport[config],   \
    193                                  &fConfigTextureSupport[config]);
    194 
    195 void GrVkCaps::initConfigTexturableTable(const GrVkInterface* interface, VkPhysicalDevice physDev) {
    196     // Base texture support
    197     SET_CONFIG_IS_TEXTURABLE(kAlpha_8_GrPixelConfig);
    198     SET_CONFIG_IS_TEXTURABLE(kRGB_565_GrPixelConfig);
    199     SET_CONFIG_IS_TEXTURABLE(kRGBA_4444_GrPixelConfig);
    200     SET_CONFIG_IS_TEXTURABLE(kRGBA_8888_GrPixelConfig);
    201     SET_CONFIG_IS_TEXTURABLE(kBGRA_8888_GrPixelConfig);
    202 
    203     SET_CONFIG_IS_TEXTURABLE(kIndex_8_GrPixelConfig);
    204     SET_CONFIG_IS_TEXTURABLE(kSRGBA_8888_GrPixelConfig);
    205 
    206     // Compressed texture support
    207     SET_CONFIG_IS_TEXTURABLE(kETC1_GrPixelConfig);
    208     SET_CONFIG_IS_TEXTURABLE(kLATC_GrPixelConfig);
    209     SET_CONFIG_IS_TEXTURABLE(kR11_EAC_GrPixelConfig);
    210     SET_CONFIG_IS_TEXTURABLE(kASTC_12x12_GrPixelConfig);
    211 
    212     // Float texture support
    213     SET_CONFIG_IS_TEXTURABLE(kRGBA_float_GrPixelConfig);
    214     SET_CONFIG_IS_TEXTURABLE(kRGBA_half_GrPixelConfig);
    215     SET_CONFIG_IS_TEXTURABLE(kAlpha_half_GrPixelConfig);
    216 }
    217 
    218 #define SET_CONFIG_CAN_STENCIL(config)                                                    \
    219     bool SK_MACRO_APPEND_LINE(linearSupported);                                           \
    220     bool SK_MACRO_APPEND_LINE(optimalSupported);                                          \
    221     format_supported_for_feature(interface,                                               \
    222                                  physDev,                                                 \
    223                                  config.fInternalFormat,                                  \
    224                                  VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT,          \
    225                                  &SK_MACRO_APPEND_LINE(linearSupported),                  \
    226                                  &SK_MACRO_APPEND_LINE(optimalSupported));                \
    227     if (SK_MACRO_APPEND_LINE(linearSupported)) fLinearStencilFormats.push_back(config);   \
    228     if (SK_MACRO_APPEND_LINE(optimalSupported)) fStencilFormats.push_back(config);
    229 
    230 void GrVkCaps::initStencilFormats(const GrVkInterface* interface, VkPhysicalDevice physDev) {
    231     // Build up list of legal stencil formats (though perhaps not supported on
    232     // the particular gpu/driver) from most preferred to least.
    233 
    234     static const StencilFormat
    235                   // internal Format             stencil bits      total bits        packed?
    236         gS8    = { VK_FORMAT_S8_UINT,            8,                 8,               false },
    237         gD24S8 = { VK_FORMAT_D24_UNORM_S8_UINT,  8,                32,               true };
    238 
    239     // I'm simply assuming that these two will be supported since they are used in example code.
    240     // TODO: Actaully figure this out
    241     SET_CONFIG_CAN_STENCIL(gS8);
    242     SET_CONFIG_CAN_STENCIL(gD24S8);
    243 }
    244 
    245