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